From 4ae94669fa23c2c117fff83adde8de703a27186a Mon Sep 17 00:00:00 2001
From: Ryan Izard <rizard@g.clemson.edu>
Date: Wed, 18 Jun 2014 17:59:48 -0400
Subject: [PATCH] Changes so far

Refactored structure of core components to work with openflowj-loxi.
Presently refactoring Routing, Firewall, Forwarding, DeviceManager,
LinkDiscovery, Topology, and LearningSwitch.
Hub has been refactored.
---
 .../core/ControllerId.java                    |   61 +
 .../core/Deliverable.java                     |   38 +
 .../core/DeliverableListenableFuture.java     |   22 +
 .../core/GenTableMap.java                     |  136 +
 .../core/GenTableNotFoundException.java       |   44 +
 .../net/floodlightcontroller/core/HARole.java |   88 +
 .../core/IFloodlightProviderService.java      |  227 +-
 .../core/IHAListener.java                     |   45 -
 .../core/IOFConnection.java                   |   62 +
 .../core/IOFConnectionBackend.java            |   23 +
 .../core/IOFMessageListener.java              |    4 +-
 .../core/IOFMessageWriter.java                |   79 +
 .../floodlightcontroller/core/IOFSwitch.java  |  669 ----
 .../core/IOFSwitchBackend.java                |  189 ++
 .../core/IOFSwitchDriver.java                 |    9 +-
 .../core/IOFSwitchListener.java               |   17 +-
 .../core/ImmutablePort.java                   |  561 ----
 .../core/LogicalOFMessageCategory.java        |   68 +
 .../net/floodlightcontroller/core/Main.java   |   84 +-
 .../core/OFConnection.java                    |  409 +++
 .../core/OFConnectionCounters.java            |  710 +++++
 .../core/OFErrorMsgException.java             |   28 +
 .../core/OFMessageFilterManager.java          |   16 +-
 .../floodlightcontroller/core/OFSwitch.java   | 1131 +++++++
 .../core/OFSwitchBase.java                    | 1579 ----------
 .../core/PortChangeEvent.java                 |   54 +
 .../core/PortChangeType.java                  |    8 +
 .../floodlightcontroller/core/RoleInfo.java   |   53 +-
 .../core/SwitchDescription.java               |  182 ++
 .../core/SwitchDisconnectedException.java     |   23 +
 ...witchDriverSubHandshakeAlreadyStarted.java |   15 -
 .../SwitchDriverSubHandshakeCompleted.java    |   19 -
 .../SwitchDriverSubHandshakeException.java    |   27 -
 .../SwitchDriverSubHandshakeNotStarted.java   |   16 -
 ...witchDriverSubHandshakeStateException.java |   16 -
 .../core/SwitchSyncRepresentation.java        |  173 +-
 .../core/internal/Controller.java             | 2696 -----------------
 .../core/internal/ControllerCounters.java     |   48 +
 .../core/internal/FloodlightProvider.java     |   29 +-
 .../internal/HandshakeTimeoutHandler.java     |   29 +-
 .../internal/IAppHandshakePluginFactory.java  |   19 +
 .../internal/INewOFConnectionListener.java    |   19 +
 .../core/internal/IOFConnectionListener.java  |   12 +
 .../core/internal/IOFSwitchManager.java       |  124 +
 .../core/internal/IOFSwitchService.java       |  111 +
 .../core/internal/ISwitchDriverRegistry.java  |   60 -
 .../internal/NaiiveSwitchDriverRegistry.java  |  105 -
 .../internal/NaiveSwitchDriverRegistry.java   |  102 +
 .../core/internal/NiciraRoleUtils.java        |   40 +
 ...eoutException.java => OFAuxException.java} |   29 +-
 .../core/internal/OFChannelHandler.java       | 1788 -----------
 .../core/internal/OFFeaturesReplyFuture.java  |   72 -
 .../core/internal/OFMessageDecoder.java       |   60 -
 .../core/internal/OFMessageEncoder.java       |   56 -
 .../core/internal/OFMessageFuture.java        |  171 --
 .../core/internal/OFStatisticsFuture.java     |   80 -
 .../internal/OFSwitchAppHandshakePlugin.java  |  116 +
 .../internal/OFSwitchHandshakeHandler.java    | 1886 ++++++++++++
 .../core/internal/OFSwitchImpl.java           |   46 -
 .../core/internal/OFSwitchManager.java        |  756 +++++
 .../internal/OpenflowPipelineFactory.java     |   77 -
 .../core/internal/PluginResult.java           |   40 +
 .../core/internal/RoleManager.java            |  258 ++
 .../core/internal/RoleManagerCounters.java    |   32 +
 .../core/internal/SwitchEvent.java            |   18 +
 .../core/internal/SwitchManagerCounters.java  |  208 ++
 .../core/module/ApplicationLoader.java        |  179 --
 ...ightModuleConfigFileNotFoundException.java |   10 +
 .../core/module/FloodlightModuleContext.java  |  124 -
 .../module/FloodlightModuleException.java     |   37 -
 .../core/module/FloodlightModuleLoader.java   |  501 ---
 .../core/module/FloodlightModulePriority.java |   58 +
 .../core/module/FloodlightServices.java       |    5 +
 .../core/module/IApplicationService.java      |    5 -
 .../core/module/IFloodlightModule.java        |   92 -
 .../core/module/IFloodlightModuleContext.java |   59 -
 .../core/module/IFloodlightService.java       |   27 -
 .../core/module/IModuleService.java           |   18 -
 .../core/module/ModuleLoaderResource.java     |  120 -
 .../floodlightcontroller/core/module/Run.java |   20 +
 .../core/rest/AggregateStatistics.java        |   39 +
 .../core/rest/SwitchRepresentation.java       |  116 +
 .../core/rest/TableStatistics.java            |   45 +
 .../core/types/SwitchMessagePair.java         |    2 +-
 .../core/util/URIUtil.java                    |   10 +
 .../core/web/AllSwitchStatisticsResource.java |   44 +-
 .../core/web/ControllerSwitchesResource.java  |   22 +-
 .../web/SwitchCounterCategoriesResource.java  |    6 +-
 .../core/web/SwitchCounterResource.java       |    6 +-
 .../core/web/SwitchResourceBase.java          |   59 +-
 .../core/web/SwitchRoleResource.java          |    4 +-
 .../core/web/SwitchStatisticsResource.java    |   15 +-
 .../serializers/ByteArrayMACSerializer.java   |    2 +-
 .../core/web/serializers/DPIDSerializer.java  |    2 +-
 .../core/web/serializers/MACSerializer.java   |    2 +-
 .../counter/CounterStore.java                 |   25 +-
 .../counter/ICounterStoreService.java         |    2 +-
 .../counter/NullCounterStore.java             |    2 +-
 .../debugcounter/CounterNode.java             |  338 +++
 .../debugcounter/DebugCounter.java            |  741 -----
 .../debugcounter/DebugCounterImpl.java        |  141 +
 .../debugcounter/DebugCounterResource.java    |  119 +
 .../DebugCounterResourceBase.java             |   16 -
 .../debugcounter/DebugCounterServiceImpl.java |  251 ++
 .../debugcounter/IDebugCounter.java           |   38 -
 .../debugcounter/IDebugCounterService.java    |  259 --
 .../debugcounter/MockDebugCounterService.java |  115 +
 .../debugcounter/NullDebugCounter.java        |  162 -
 .../debugevent/DebugEventResource.java        |  207 ++
 .../debugevent/DebugEventService.java         |  711 +++++
 .../debugevent/Event.java                     |   10 +-
 .../debugevent/IDebugEventService.java        |  189 --
 .../debugevent/IEventCategory.java            |   30 +
 .../debugevent/MockDebugEventService.java     |  128 +
 .../devicemanager/IDevice.java                |   12 +-
 .../devicemanager/IDeviceService.java         |   40 +-
 .../devicemanager/SwitchPort.java             |   21 +-
 .../internal/AttachmentPoint.java             |   45 +-
 .../devicemanager/internal/Device.java        |   33 +-
 .../internal/DeviceIterator.java              |   32 +-
 .../internal/DeviceManagerImpl.java           |  255 +-
 .../internal/DeviceSyncRepresentation.java    |   17 +-
 .../devicemanager/internal/Entity.java        |   49 +-
 .../devicemanager/internal/IndexedEntity.java |    4 +-
 .../firewall/Firewall.java                    |   85 +-
 .../firewall/FirewallRule.java                |  237 +-
 .../firewall/FirewallRuleSerializer.java      |   28 +-
 .../firewall/FirewallRulesResource.java       |   50 +-
 .../firewall/RuleWildcardsPair.java           |    4 +-
 .../firewall/WildcardsPair.java               |    9 +-
 .../forwarding/Forwarding.java                |   83 +-
 .../net/floodlightcontroller/hub/Hub.java     |   50 +-
 .../linkdiscovery/ILinkDiscovery.java         |   42 +-
 .../linkdiscovery/ILinkDiscoveryService.java  |   19 +-
 .../linkdiscovery/LinkInfo.java               |   30 +-
 .../floodlightcontroller/packet/BSNPROBE.java |    2 +-
 .../floodlightcontroller/packet/Ethernet.java |   48 +-
 .../perfmon/IPktInProcessingTimeService.java  |    2 +-
 .../perfmon/NullPktInProcessingTime.java      |    2 +-
 .../perfmon/PktInProcessingTime.java          |    4 +-
 .../routing/BroadcastTree.java                |   26 +-
 .../routing/ForwardingBase.java               |  251 +-
 .../routing/IRoutingDecision.java             |    6 +-
 .../routing/IRoutingService.java              |   21 +-
 .../floodlightcontroller/routing/Link.java    |   71 +-
 .../floodlightcontroller/routing/Route.java   |    4 +-
 .../floodlightcontroller/routing/RouteId.java |   22 +-
 .../routing/RoutingDecision.java              |   16 +-
 .../topology/Cluster.java                     |   26 +-
 .../topology/ITopologyService.java            |  371 +--
 .../topology/NodePortTuple.java               |   40 +-
 .../topology/TopologyInstance.java            |  189 +-
 .../topology/TopologyManager.java             |  287 +-
 .../util/OFMessageDamper.java                 |    9 +-
 .../virtualnetwork/VirtualNetworkFilter.java  |   16 +-
 .../org/openflow/protocol/Instantiable.java   |   31 -
 .../org/openflow/protocol/OFBarrierReply.java |   32 -
 .../openflow/protocol/OFBarrierRequest.java   |   32 -
 .../org/openflow/protocol/OFEchoReply.java    |   36 -
 .../org/openflow/protocol/OFEchoRequest.java  |  101 -
 .../java/org/openflow/protocol/OFError.java   |  325 --
 .../openflow/protocol/OFFeaturesReply.java    |  261 --
 .../openflow/protocol/OFFeaturesRequest.java  |   36 -
 .../java/org/openflow/protocol/OFFlowMod.java |  389 ---
 .../org/openflow/protocol/OFFlowRemoved.java  |  294 --
 .../openflow/protocol/OFGetConfigReply.java   |   29 -
 .../openflow/protocol/OFGetConfigRequest.java |   32 -
 .../java/org/openflow/protocol/OFHello.java   |   39 -
 .../java/org/openflow/protocol/OFMatch.java   | 1145 -------
 .../openflow/protocol/OFMatchBeanInfo.java    |  101 -
 .../openflow/protocol/OFMatchWithSwDpid.java  |   92 -
 .../java/org/openflow/protocol/OFMessage.java |  336 --
 .../protocol/OFMessageContextStore.java       |   39 -
 .../org/openflow/protocol/OFPacketIn.java     |  211 --
 .../org/openflow/protocol/OFPacketOut.java    |  260 --
 .../org/openflow/protocol/OFPacketQueue.java  |  142 -
 .../org/openflow/protocol/OFPhysicalPort.java |  614 ----
 .../java/org/openflow/protocol/OFPort.java    |   43 -
 .../java/org/openflow/protocol/OFPortMod.java |  182 --
 .../org/openflow/protocol/OFPortStatus.java   |  144 -
 .../protocol/OFQueueGetConfigReply.java       |  125 -
 .../protocol/OFQueueGetConfigRequest.java     |   95 -
 .../org/openflow/protocol/OFQueueProp.java    |  175 --
 .../org/openflow/protocol/OFSetConfig.java    |   29 -
 .../protocol/OFStatisticsMessageBase.java     |  180 --
 .../openflow/protocol/OFStatisticsReply.java  |   46 -
 .../protocol/OFStatisticsRequest.java         |   32 -
 .../org/openflow/protocol/OFSwitchConfig.java |  118 -
 .../java/org/openflow/protocol/OFType.java    |  249 --
 .../java/org/openflow/protocol/OFVendor.java  |  131 -
 .../java/org/openflow/protocol/Wildcards.java |  603 ----
 .../openflow/protocol/action/OFAction.java    |  173 --
 .../protocol/action/OFActionDataLayer.java    |  109 -
 .../action/OFActionDataLayerDestination.java  |   35 -
 .../action/OFActionDataLayerSource.java       |   35 -
 .../protocol/action/OFActionEnqueue.java      |  136 -
 .../action/OFActionNetworkLayerAddress.java   |   98 -
 .../OFActionNetworkLayerDestination.java      |   35 -
 .../action/OFActionNetworkLayerSource.java    |   35 -
 .../action/OFActionNetworkTypeOfService.java  |  110 -
 .../protocol/action/OFActionOutput.java       |  161 -
 .../action/OFActionStripVirtualLan.java       |   60 -
 .../action/OFActionTransportLayer.java        |   98 -
 .../OFActionTransportLayerDestination.java    |   35 -
 .../action/OFActionTransportLayerSource.java  |   35 -
 .../protocol/action/OFActionType.java         |  203 --
 .../protocol/action/OFActionVendor.java       |   94 -
 .../action/OFActionVendorGeneric.java         |   96 -
 .../action/OFActionVirtualLanIdentifier.java  |   98 -
 .../OFActionVirtualLanPriorityCodePoint.java  |  100 -
 .../protocol/factory/BasicFactory.java        |  346 ---
 .../factory/MessageParseException.java        |   45 -
 .../protocol/factory/OFActionFactory.java     |   61 -
 .../factory/OFActionFactoryAware.java         |   31 -
 .../protocol/factory/OFMessageFactory.java    |   55 -
 .../factory/OFMessageFactoryAware.java        |   35 -
 .../protocol/factory/OFStatisticsFactory.java |   72 -
 .../factory/OFStatisticsFactoryAware.java     |   31 -
 .../factory/OFVendorActionFactory.java        |   43 -
 .../factory/OFVendorActionRegistry.java       |   50 -
 .../protocol/factory/OFVendorDataFactory.java |   69 -
 .../factory/OFVendorDataFactoryAware.java     |   28 -
 .../OFFeaturesReplyJSONSerializer.java        |   57 -
 .../serializers/OFMatchJSONSerializer.java    |   91 -
 .../StringDpidToLongJSONDeserializer.java     |   23 -
 .../OFAggregateStatisticsReply.java           |  130 -
 .../OFAggregateStatisticsRequest.java         |  135 -
 .../statistics/OFDescriptionStatistics.java   |  246 --
 .../statistics/OFFlowStatisticsReply.java     |  359 ---
 .../statistics/OFFlowStatisticsRequest.java   |  135 -
 .../statistics/OFPortStatisticsReply.java     |  356 ---
 .../statistics/OFPortStatisticsRequest.java   |   88 -
 .../statistics/OFQueueStatisticsReply.java    |  175 --
 .../statistics/OFQueueStatisticsRequest.java  |  107 -
 .../protocol/statistics/OFStatistics.java     |   45 -
 .../protocol/statistics/OFStatisticsType.java |  317 --
 .../statistics/OFTableStatistics.java         |  223 --
 .../statistics/OFVendorStatistics.java        |   83 -
 .../vendor/OFBasicVendorDataType.java         |   71 -
 .../protocol/vendor/OFBasicVendorId.java      |  162 -
 .../vendor/OFByteArrayVendorData.java         |   94 -
 .../protocol/vendor/OFVendorData.java         |   44 -
 .../protocol/vendor/OFVendorDataType.java     |   79 -
 .../openflow/protocol/vendor/OFVendorId.java  |   85 -
 .../java/org/openflow/util/HexString.java     |   93 -
 .../java/org/openflow/util/IProducer.java     |    9 -
 .../org/openflow/util/LRULinkedHashMap.java   |   42 -
 .../org/openflow/util/ProducerConsumer.java   |  223 --
 .../openflow/util/StringByteSerializer.java   |   58 -
 src/main/java/org/openflow/util/U16.java      |   28 -
 src/main/java/org/openflow/util/U32.java      |   28 -
 src/main/java/org/openflow/util/U64.java      |   30 -
 src/main/java/org/openflow/util/U8.java       |   28 -
 src/main/java/org/openflow/util/Unsigned.java |  212 --
 .../vendor/nicira/OFNiciraVendorData.java     |   98 -
 .../nicira/OFNiciraVendorExtensions.java      |   30 -
 .../vendor/nicira/OFRoleReplyVendorData.java  |   66 -
 .../nicira/OFRoleRequestVendorData.java       |   66 -
 .../vendor/nicira/OFRoleVendorData.java       |  113 -
 .../vendor/openflow/OFOpenFlowVendorData.java |   98 -
 .../openflow/OFOpenFlowVendorExtensions.java  |   47 -
 .../openflow/OFQueueDeleteVendorData.java     |   52 -
 .../openflow/OFQueueModifyVendorData.java     |   52 -
 .../vendor/openflow/OFQueueVendorData.java    |  119 -
 .../org/sdnplatform/sync/ISyncService.java    |    2 +
 .../sync/internal/SyncTorture.java            |  196 --
 .../sync/internal/config/ClusterConfig.java   |    1 +
 .../sync/internal/util/ByteArray.java         |    2 +-
 .../core/internal/ControllerTest.java         |   34 +-
 .../core/internal/OFChannelHandlerTest.java   |   12 +-
 .../util/OFMessageDamperMockSwitch.java       |    4 +-
 .../openflow/protocol/BasicFactoryTest.java   |  134 -
 .../openflow/protocol/OFActionTypeTest.java   |   37 -
 .../openflow/protocol/OFBarrierReplyTest.java |   36 -
 .../protocol/OFBarrierRequestTest.java        |   36 -
 .../org/openflow/protocol/OFErrorTest.java    |   88 -
 .../protocol/OFFeaturesReplyTest.java         |   62 -
 .../openflow/protocol/OFFlowRemovedTest.java  |   43 -
 .../protocol/OFGetConfigReplyTest.java        |   38 -
 .../protocol/OFGetConfigRequestTest.java      |   36 -
 .../org/openflow/protocol/OFMatchTest.java    |   92 -
 .../protocol/OFMessageContextStoreTest.java   |   31 -
 .../openflow/protocol/OFPacketOutTest.java    |   45 -
 .../openflow/protocol/OFPortConfigTest.java   |   39 -
 .../openflow/protocol/OFPortStatusTest.java   |   44 -
 .../openflow/protocol/OFSetConfigTest.java    |   38 -
 .../protocol/OFStatisticsReplyTest.java       |   77 -
 .../protocol/OFStatisticsRequestTest.java     |   79 -
 .../protocol/OFStatisticsTypeTest.java        |   37 -
 .../org/openflow/protocol/OFTypeTest.java     |   39 -
 .../org/openflow/protocol/OFVendorTest.java   |  226 --
 .../org/openflow/protocol/WildcardsTest.java  |  162 -
 .../protocol/action/MockVendorAction.java     |   41 -
 .../action/MockVendorActionFactory.java       |   15 -
 .../action/OFVendorActionRegistryTest.java    |   17 -
 .../java/org/openflow/util/HexStringTest.java |   88 -
 .../java/org/openflow/util/OFTestCase.java    |   36 -
 src/test/java/org/openflow/util/U16Test.java  |   33 -
 src/test/java/org/openflow/util/U32Test.java  |   32 -
 src/test/java/org/openflow/util/U64Test.java  |   34 -
 src/test/java/org/openflow/util/U8Test.java   |   32 -
 .../java/org/openflow/util/UnsignedTest.java  |   83 -
 302 files changed, 11286 insertions(+), 28376 deletions(-)
 create mode 100644 src/main/java/net/floodlightcontroller/core/ControllerId.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/Deliverable.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/DeliverableListenableFuture.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/GenTableMap.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/HARole.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/IHAListener.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/IOFConnection.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/IOFConnectionBackend.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/IOFMessageWriter.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/IOFSwitch.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/ImmutablePort.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/LogicalOFMessageCategory.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/OFConnection.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/OFSwitch.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/OFSwitchBase.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/PortChangeEvent.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/PortChangeType.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/SwitchDescription.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/SwitchDisconnectedException.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeAlreadyStarted.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeCompleted.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeException.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeNotStarted.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeStateException.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/Controller.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/IAppHandshakePluginFactory.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/INewOFConnectionListener.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/IOFConnectionListener.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/IOFSwitchService.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/NaiiveSwitchDriverRegistry.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/NiciraRoleUtils.java
 rename src/main/java/net/floodlightcontroller/core/internal/{HandshakeTimeoutException.java => OFAuxException.java} (51%)
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFFeaturesReplyFuture.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/PluginResult.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/RoleManager.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/RoleManagerCounters.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/SwitchEvent.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/internal/SwitchManagerCounters.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/ApplicationLoader.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/module/FloodlightModuleConfigFileNotFoundException.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/module/FloodlightModulePriority.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/module/FloodlightServices.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/IApplicationService.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/IModuleService.java
 delete mode 100644 src/main/java/net/floodlightcontroller/core/module/ModuleLoaderResource.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/module/Run.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/rest/AggregateStatistics.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/rest/SwitchRepresentation.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/rest/TableStatistics.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/util/URIUtil.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugcounter/CounterNode.java
 delete mode 100644 src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugcounter/DebugCounterImpl.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResource.java
 delete mode 100644 src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugcounter/DebugCounterServiceImpl.java
 delete mode 100644 src/main/java/net/floodlightcontroller/debugcounter/IDebugCounter.java
 delete mode 100644 src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugcounter/MockDebugCounterService.java
 delete mode 100644 src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugevent/DebugEventResource.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugevent/DebugEventService.java
 delete mode 100644 src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugevent/IEventCategory.java
 create mode 100644 src/main/java/net/floodlightcontroller/debugevent/MockDebugEventService.java
 delete mode 100644 src/main/java/org/openflow/protocol/Instantiable.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFBarrierReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFBarrierRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFEchoReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFEchoRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFError.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFFeaturesReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFFeaturesRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFFlowMod.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFFlowRemoved.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFGetConfigReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFGetConfigRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFHello.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFMatch.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFMatchBeanInfo.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFMessage.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFMessageContextStore.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFPacketIn.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFPacketOut.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFPacketQueue.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFPhysicalPort.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFPort.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFPortMod.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFPortStatus.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFQueueProp.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFSetConfig.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFStatisticsReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFStatisticsRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFSwitchConfig.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFType.java
 delete mode 100644 src/main/java/org/openflow/protocol/OFVendor.java
 delete mode 100644 src/main/java/org/openflow/protocol/Wildcards.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFAction.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionDataLayer.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionEnqueue.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionOutput.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionType.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionVendor.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java
 delete mode 100644 src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/BasicFactory.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/MessageParseException.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFActionFactory.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFMessageFactory.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java
 delete mode 100644 src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java
 delete mode 100644 src/main/java/org/openflow/protocol/serializers/OFFeaturesReplyJSONSerializer.java
 delete mode 100644 src/main/java/org/openflow/protocol/serializers/OFMatchJSONSerializer.java
 delete mode 100644 src/main/java/org/openflow/protocol/serializers/StringDpidToLongJSONDeserializer.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFStatistics.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java
 delete mode 100644 src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java
 delete mode 100644 src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java
 delete mode 100644 src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java
 delete mode 100644 src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java
 delete mode 100644 src/main/java/org/openflow/protocol/vendor/OFVendorData.java
 delete mode 100644 src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java
 delete mode 100644 src/main/java/org/openflow/protocol/vendor/OFVendorId.java
 delete mode 100644 src/main/java/org/openflow/util/HexString.java
 delete mode 100644 src/main/java/org/openflow/util/IProducer.java
 delete mode 100644 src/main/java/org/openflow/util/LRULinkedHashMap.java
 delete mode 100644 src/main/java/org/openflow/util/ProducerConsumer.java
 delete mode 100644 src/main/java/org/openflow/util/StringByteSerializer.java
 delete mode 100644 src/main/java/org/openflow/util/U16.java
 delete mode 100644 src/main/java/org/openflow/util/U32.java
 delete mode 100644 src/main/java/org/openflow/util/U64.java
 delete mode 100644 src/main/java/org/openflow/util/U8.java
 delete mode 100644 src/main/java/org/openflow/util/Unsigned.java
 delete mode 100644 src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java
 delete mode 100644 src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java
 delete mode 100644 src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java
 delete mode 100644 src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java
 delete mode 100644 src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java
 delete mode 100644 src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java
 delete mode 100644 src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java
 delete mode 100644 src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java
 delete mode 100644 src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java
 delete mode 100644 src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java
 delete mode 100644 src/main/java/org/sdnplatform/sync/internal/SyncTorture.java
 delete mode 100644 src/test/java/org/openflow/protocol/BasicFactoryTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFActionTypeTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFBarrierReplyTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFBarrierRequestTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFErrorTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFFlowRemovedTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFMatchTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFPacketOutTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFPortConfigTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFPortStatusTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFSetConfigTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFTypeTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/OFVendorTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/WildcardsTest.java
 delete mode 100644 src/test/java/org/openflow/protocol/action/MockVendorAction.java
 delete mode 100644 src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java
 delete mode 100644 src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java
 delete mode 100644 src/test/java/org/openflow/util/HexStringTest.java
 delete mode 100644 src/test/java/org/openflow/util/OFTestCase.java
 delete mode 100644 src/test/java/org/openflow/util/U16Test.java
 delete mode 100644 src/test/java/org/openflow/util/U32Test.java
 delete mode 100644 src/test/java/org/openflow/util/U64Test.java
 delete mode 100644 src/test/java/org/openflow/util/U8Test.java
 delete mode 100644 src/test/java/org/openflow/util/UnsignedTest.java

diff --git a/src/main/java/net/floodlightcontroller/core/ControllerId.java b/src/main/java/net/floodlightcontroller/core/ControllerId.java
new file mode 100644
index 000000000..6fd347b23
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/ControllerId.java
@@ -0,0 +1,61 @@
+package net.floodlightcontroller.core;
+
+import org.sdnplatform.sync.ISyncService;
+import org.sdnplatform.sync.internal.config.ClusterConfig;
+
+import com.google.common.base.Optional;
+
+/** This class represents a unique id of this controller node. It is derived from
+ *  the node id as returned by {@link ISyncService#getLocalNodeId()}.
+ *  <p>
+ *  Note that the unconfigured Node Id is not supported. Users are encouraged to
+ *  represent an unconfigured Controller Node by {@link Optional#absent()}.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class ControllerId {
+    private final short nodeId;
+
+    private ControllerId(short nodeId) {
+        if(nodeId == ClusterConfig.NODE_ID_UNCONFIGURED)
+            throw new IllegalArgumentException("nodeId is unconfigured");
+
+        this.nodeId = nodeId;
+    }
+
+    public short getNodeId() {
+        return nodeId;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + nodeId;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        ControllerId other = (ControllerId) obj;
+        if (nodeId != other.nodeId)
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return Short.toString(nodeId);
+    }
+
+    public static ControllerId of(short nodeId) {
+        return new ControllerId(nodeId);
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/Deliverable.java b/src/main/java/net/floodlightcontroller/core/Deliverable.java
new file mode 100644
index 000000000..c82f31d85
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/Deliverable.java
@@ -0,0 +1,38 @@
+package net.floodlightcontroller.core;
+
+/**
+ * abstracts the 'back side' of a Future that is being listened on, i.e., an
+ * object that receives a result or an error of the computaton once it is ready.
+ * A deliverable can accept multiple computation results, indicated by the
+ * return value of deliver.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ * @param <T>
+ *            type of the result of the computation
+ */
+public interface Deliverable<T> {
+    public static enum Status {
+        DONE,
+        CONTINUE
+    }
+
+    /**
+     * deliver the result after a successful computation has completed
+     *
+     * @param msg
+     *            result
+     * @return whether the delivery is complete with this result.
+     **/
+    public void deliver(T msg);
+
+    /** deliver an error result for the computation
+     * @param cause throwable that describes the error
+     */
+    void deliverError(Throwable cause);
+
+    /** whether or not the deliverable has been completed before.
+     */
+    boolean isDone();
+
+    boolean cancel(boolean mayInterruptIfRunning);
+}
diff --git a/src/main/java/net/floodlightcontroller/core/DeliverableListenableFuture.java b/src/main/java/net/floodlightcontroller/core/DeliverableListenableFuture.java
new file mode 100644
index 000000000..1e724ac51
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/DeliverableListenableFuture.java
@@ -0,0 +1,22 @@
+package net.floodlightcontroller.core;
+
+import com.google.common.util.concurrent.AbstractFuture;
+
+/** Implementation of a ListenableFuture that provides a Deliverable interface to
+ *  the provider.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ * @see Deliverable
+ * @param <T>
+ */
+public class DeliverableListenableFuture<T> extends AbstractFuture<T> implements Deliverable<T> {
+    @Override
+    public void deliver(final T result) {
+        set(result);
+    }
+
+    @Override
+    public void deliverError(final Throwable cause) {
+        setException(cause);
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/GenTableMap.java b/src/main/java/net/floodlightcontroller/core/GenTableMap.java
new file mode 100644
index 000000000..ef32a1979
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/GenTableMap.java
@@ -0,0 +1,136 @@
+package net.floodlightcontroller.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.Immutable;
+
+import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsRequest;
+import org.projectfloodlight.openflow.types.GenTableId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+
+/** A registry for GenTables. Initialized during switch handshake, based on a
+ *  {@link OFBsnGentableDescStatsRequest}. The table for a particular switch
+ *  can be retrieved via {@link IOFSwitch#getGenTableMap()}.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+@Immutable
+public class GenTableMap {
+    private static final Logger logger = LoggerFactory.getLogger(GenTableMap.class);
+
+    private final Map<GenTableId, OFBsnGentableDescStatsEntry> idMap;
+    private final Map<String, OFBsnGentableDescStatsEntry> nameMap;
+
+    // an empty gentable map
+    private GenTableMap() {
+        idMap = ImmutableMap.of();
+        nameMap = ImmutableMap.of();
+    }
+
+    public GenTableMap(Iterable<OFBsnGentableDescStatsEntry> entries) {
+        // note: not using an ImmutableMap.Builder here, because we need to
+        // check for duplicates
+        Map<GenTableId, OFBsnGentableDescStatsEntry> idBuildMap = new LinkedHashMap<>();
+        Map<String, OFBsnGentableDescStatsEntry> nameBuildMap = new LinkedHashMap<>();
+
+        for (OFBsnGentableDescStatsEntry e : entries) {
+            GenTableId id = e.getTableId();
+            String name = e.getName();
+            if (idBuildMap.containsKey(id)) {
+                logger.warn("Duplicate table id " + id + " - entry {} present. Ignoring new entry {}",
+                        idBuildMap.get(id), e);
+                continue;
+            }
+            if (nameBuildMap.containsKey(name)) {
+                logger.warn(
+                        "Duplicate table name " + name + " - entry named {} present. Ignoring new entry {}",
+                        nameBuildMap.get(name), e);
+                continue;
+            }
+            idBuildMap.put(id, e);
+            nameBuildMap.put(name, e);
+        }
+        this.idMap = ImmutableMap.copyOf(idBuildMap);
+        this.nameMap = ImmutableMap.copyOf(nameBuildMap);
+    }
+
+    public Set<GenTableId> getIds() {
+        return idMap.keySet();
+    }
+
+    public Set<String> getNames() {
+        return nameMap.keySet();
+    }
+
+    public Collection<OFBsnGentableDescStatsEntry> getEntries() {
+        return idMap.values();
+    }
+
+    public boolean hasEntry(GenTableId id) {
+        return idMap.containsKey(id);
+    }
+
+    /** retrieve a GenTable Description from the map by id.
+     *
+     * @param id
+     * @return the retrieved gen  table description.
+     * @throws GenTableNotFoundException if no gentable with the given id was found in the map
+     */
+    @Nonnull
+    public OFBsnGentableDescStatsEntry getEntry(GenTableId id) throws GenTableNotFoundException {
+        OFBsnGentableDescStatsEntry entry = idMap.get(id);
+        if(entry == null)
+            throw new GenTableNotFoundException(id, idMap.values());
+        return entry;
+    }
+
+    public boolean hasEntry(String name) {
+        return nameMap.containsKey(name);
+    }
+
+    /** retrieve a GenTable Description from the map by name.
+     *
+     * @param name
+     * @return the retrieved gen table description.
+     * @throws GenTableNotFoundException if no gentable with the given name was found in the map
+     */
+    @Nonnull
+    public OFBsnGentableDescStatsEntry getEntry(String name) throws GenTableNotFoundException {
+        OFBsnGentableDescStatsEntry entry = nameMap.get(name);
+        if(entry == null)
+            throw new GenTableNotFoundException(name, nameMap.values());
+        return entry;
+    }
+
+    public final static GenTableMap empty() {
+        return new GenTableMap();
+    }
+
+    public static GenTableMap of(Iterable<OFBsnGentableDescStatsReply> replies) {
+        List<OFBsnGentableDescStatsEntry> allEntries = new ArrayList<>();
+        for(OFBsnGentableDescStatsReply reply: replies) {
+            allEntries.addAll(reply.getEntries());
+        }
+        return new GenTableMap(allEntries);
+    }
+
+    @Override
+    public String toString() {
+        return idMap.toString();
+    }
+
+    public int size() {
+        return idMap.size();
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java b/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java
new file mode 100644
index 000000000..544fc1e84
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/GenTableNotFoundException.java
@@ -0,0 +1,44 @@
+package net.floodlightcontroller.core;
+
+import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsEntry;
+import org.projectfloodlight.openflow.types.GenTableId;
+
+/** A GenTable was not found in the {@link GenTableMap}.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class GenTableNotFoundException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    public GenTableNotFoundException(String name, Iterable<OFBsnGentableDescStatsEntry> available) {
+        super(getMessageForName(name, available));
+    }
+
+    private static String getMessageForName(String name,
+            Iterable<OFBsnGentableDescStatsEntry> available) {
+        return String.format("Table not found: %s (available tables: %s)", name, availableDescr(available));
+    }
+
+    public GenTableNotFoundException(GenTableId id, Iterable<OFBsnGentableDescStatsEntry> available) {
+        super(getMessageForId(id, available));
+    }
+
+    private static String getMessageForId(GenTableId id,
+            Iterable<OFBsnGentableDescStatsEntry> available) {
+        return String.format("Table not found: %s (available tables: %s)", id, availableDescr(available));
+    }
+
+    private static String availableDescr(Iterable<OFBsnGentableDescStatsEntry> available) {
+        StringBuilder b = new StringBuilder();
+        boolean first = true;
+        for(OFBsnGentableDescStatsEntry e: available) {
+            if(!first)
+                b.append(", ");
+            first = false;
+            b.append(e.getName()).append("=").append(e.getTableId());
+        }
+        return b.toString();
+    }
+
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/HARole.java b/src/main/java/net/floodlightcontroller/core/HARole.java
new file mode 100644
index 000000000..0c2886f1e
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/HARole.java
@@ -0,0 +1,88 @@
+package net.floodlightcontroller.core;
+
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * HARole describes the role that a given controller node currently plays in the
+ * management of the SDN network. Controller nodes can be either
+ * <ul>
+ * <li>ACTIVE - currently controlling the network
+ * <li>STANDBY - standing by in case of a fail-over from the ACTIVE node
+ * </ul>
+ * At any given time there SHOULD be at most one ACTIVE node in the network
+ * (this invariant cannot be strictly guranteed for certain split-brain
+ * situtations). There can be multiple STANDBY controllers. There are other
+ * HA-related roles in the system. Try to not confuse them.
+ * <ul>
+ * <li>On the cluster management/bigsync layer {@link ISyncService} determines a
+ * DOMAIN LEADER / DOMAIN FOLLOWER (which are exposed via
+ * <li>On the OF layer, switch connections can be in either MASTER, SLAVE or
+ * EQUAL {@link Role} (exposed by {@link IOFSwitchListener}).
+ * </ul>
+ * Most applications and modules trying to decide something on the ACTIVE node
+ * should base that decision on the HARole.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public enum HARole {
+    /** This controller node is currently actively managing the SDN network. At any given
+     *  time, there should be at most one ACTIVE node. When the ACTIVE node fails, a STANDBY
+     *  node is determined to become ACTIVE.
+     */
+    ACTIVE(OFControllerRole.ROLE_MASTER),
+
+    /** This controller node is currently standing by and not managing the networking. There
+     *  may be more than one STANDBY nodes in the network.
+     */
+    STANDBY(OFControllerRole.ROLE_SLAVE);
+
+    private static final Logger logger = LoggerFactory.getLogger(HARole.class);
+    private final OFControllerRole ofRole;
+
+    HARole(OFControllerRole ofRole) {
+        this.ofRole = ofRole;
+    }
+
+    /** a backwards-compatible {@link #valueOf} that accepts the old terms "MASTER" and "SLAVE"
+     *  and normalizes them to ACTIVE and STANDBY.
+     *
+     * @param roleString
+     * @return an HARole
+     * @throws IllegalArgumentException - if no such role can be found.
+     */
+    public static HARole valueOfBackwardsCompatible(String roleString) throws IllegalArgumentException {
+        roleString = roleString.trim().toUpperCase();
+        if("MASTER".equals(roleString)) {
+            logger.warn("got legacy role name MASTER - normalized to ACTIVE", roleString);
+            if(logger.isDebugEnabled()) {
+               logger.debug("Legacy role call stack", new IllegalArgumentException());
+            }
+            roleString = "ACTIVE";
+        } else if ("SLAVE".equals(roleString)) {
+            logger.warn("got legacy role name SLAVE - normalized to STANDBY", roleString);
+            if(logger.isDebugEnabled()) {
+               logger.debug("Legacy role call stack", new IllegalArgumentException());
+            }
+            roleString = "STANDBY";
+        }
+        return valueOf(roleString);
+    }
+
+    public OFControllerRole getOFRole() {
+        return ofRole;
+    }
+
+    public static HARole ofOFRole(OFControllerRole role) {
+        switch(role) {
+            case ROLE_MASTER:
+            case ROLE_EQUAL:
+                return ACTIVE;
+            case ROLE_SLAVE:
+                return STANDBY;
+            default:
+                throw new IllegalArgumentException("Unmappable controller role: " + role);
+        }
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
index c0aa1fd6d..ce3e1786f 100644
--- a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
+++ b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
@@ -17,8 +17,6 @@
 
 package net.floodlightcontroller.core;
 
-import java.util.HashMap;
-
 import java.util.List;
 import java.util.Set;
 import java.util.Map;
@@ -26,11 +24,22 @@ import java.util.Map;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.packet.Ethernet;
 
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.vendor.nicira.OFRoleVendorData;
-
+import org.jboss.netty.util.Timer;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.HARole;
+import net.floodlightcontroller.core.IHAListener;
+import net.floodlightcontroller.core.IInfoProvider;
+import net.floodlightcontroller.core.IOFMessageListener;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.RoleInfo;
+import net.floodlightcontroller.core.internal.RoleManager;
+import net.floodlightcontroller.core.internal.Controller.IUpdate;
+import net.floodlightcontroller.core.internal.Controller.ModuleLoaderState;
+
+import net.floodlightcontroller.core.FloodlightContextStore;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
 /**
  * The interface exposed by the core bundle that allows you to interact
  * with connected switches.
@@ -45,38 +54,7 @@ public interface IFloodlightProviderService extends
      * representation of the payload of a packet-in message.
      */
     public static final String CONTEXT_PI_PAYLOAD =
-            "net.floodlightcontroller.core.IFloodlightProvider.piPayload";
-
-    /**
-     * The role of the controller as used by the OF 1.2 and OVS failover and
-     * load-balancing mechanism.
-     */
-    public static enum Role {
-        EQUAL(OFRoleVendorData.NX_ROLE_OTHER),
-        MASTER(OFRoleVendorData.NX_ROLE_MASTER),
-        SLAVE(OFRoleVendorData.NX_ROLE_SLAVE);
-
-        private final int nxRole;
-
-        private Role(int nxRole) {
-            this.nxRole = nxRole;
-        }
-
-        private static Map<Integer,Role> nxRoleToEnum
-                = new HashMap<Integer,Role>();
-        static {
-            for(Role r: Role.values())
-                nxRoleToEnum.put(r.toNxRole(), r);
-        }
-        public int toNxRole() {
-            return nxRole;
-        }
-        // Return the enum representing the given nxRole or null if no
-        // such role exists
-        public static Role fromNxRole(int nxRole) {
-            return nxRoleToEnum.get(nxRole);
-        }
-    };
+            "org.projectfloodlight.core.IFloodlightProvider.piPayload";
 
     /**
      * A FloodlightContextStore object that can be used to retrieve the
@@ -85,6 +63,15 @@ public interface IFloodlightProviderService extends
     public static final FloodlightContextStore<Ethernet> bcStore =
             new FloodlightContextStore<Ethernet>();
 
+    /**
+     * Service name used in the service directory representing
+     * the OpenFlow controller-switch channel
+     *
+     * @see  ILocalServiceAddressTracker
+     * @see  IClusterServiceAddressDirectory
+     */
+    public static final String SERVICE_DIRECTORY_SERVICE_NAME = "openflow";
+
     /**
      * Adds an OpenFlow message listener
      * @param type The OFType the component wants to listen for
@@ -106,77 +93,52 @@ public interface IFloodlightProviderService extends
     public Map<OFType, List<IOFMessageListener>> getListeners();
 
     /**
-     * If the switch with the given DPID is known to any controller in the
-     * cluster, this method returns the associated IOFSwitch instance. As such
-     * the returned switches not necessarily connected or in master role for
-     * the local controller.
-     *
-     * Multiple calls to this method with the same DPID may return different
-     * IOFSwitch references. A caller must not store or otherwise rely on
-     * IOFSwitch references to be constant over the lifecycle of a switch.
-     *
-     * @param dpid the dpid of the switch to query
-     * @return the IOFSwitch instance associated with the dpid, null if no
-     * switch with the dpid is known to the cluster
+     * Get the current role of the controller
      */
-    public IOFSwitch getSwitch(long dpid);
+    public HARole getRole();
 
     /**
-     * Returns a snapshot of the set DPIDs for all known switches.
-     *
-     * The returned set is owned by the caller: the caller can modify it at
-     * will and changes to the known switches are not reflected in the returned
-     * set. The caller needs to call getAllSwitchDpids() if an updated
-     * version is needed.
-     *
-     * See {@link #getSwitch(long)} for what  "known" switch is.
-     * @return the set of DPIDs of all known switches
+     * Get the current role of the controller
      */
-    public Set<Long> getAllSwitchDpids();
+    public RoleInfo getRoleInfo();
 
     /**
-     * Return a snapshot
-     * FIXME: asdf
-     * @return
+     * Get the current mapping of controller IDs to their IP addresses
+     * Returns a copy of the current mapping.
+     * @see IHAListener
      */
-    public Map<Long,IOFSwitch> getAllSwitchMap();
+    public Map<String,String> getControllerNodeIPs();
 
     /**
-     * Get the current role of the controller
+     * Gets the ID of the controller
      */
-    public Role getRole();
+    public String getControllerId();
 
     /**
-     * Get the current role of the controller
+     * Gets the controller hostname
+     * @return the controller hostname
      */
-    public RoleInfo getRoleInfo();
+    public String getOFHostname();
 
     /**
-     * Get the current mapping of controller IDs to their IP addresses
-     * Returns a copy of the current mapping.
-     * @see IHAListener
+     * Gets the controller's openflow port
+     * @return the controller's openflow port
      */
-    public Map<String,String> getControllerNodeIPs();
-
+    public int getOFPort();
 
     /**
      * Set the role of the controller
      * @param role The new role for the controller node
      * @param changeDescription The reason or other information for this role change
      */
-    public void setRole(Role role, String changeDescription);
-
-    /**
-     * Add a switch listener
-     * @param listener The module that wants to listen for events
-     */
-    public void addOFSwitchListener(IOFSwitchListener listener);
+    public void setRole(HARole role, String changeDescription);
 
     /**
-     * Remove a switch listener
-     * @param listener The The module that no longer wants to listen for events
+     * Add an update task for asynchronous, serialized execution
+     *
+     * @param update
      */
-    public void removeOFSwitchListener(IOFSwitchListener listener);
+    public void addUpdateToQueue(IUpdate update);
 
     /**
      * Adds a listener for HA role events
@@ -190,53 +152,13 @@ public interface IFloodlightProviderService extends
      */
     public void removeHAListener(IHAListener listener);
 
-    /**
-     * Add a listener for ready-for-flow-reconcile events
-     * @param l
-     */
-    public void addReadyForReconcileListener(IReadyForReconcileListener l);
-
-    /**
-     * Terminate the process
-     */
-    public void terminate();
-
-    /**
-     * Re-injects an OFMessage back into the packet processing chain
-     * @param sw The switch to use for the message
-     * @param msg the message to inject
-     * @return True if successfully re-injected, false otherwise
-     * @throws NullPointerException if switch or msg is null
-     */
-    public boolean injectOfMessage(IOFSwitch sw, OFMessage msg);
-
-    /**
-     * Re-injects an OFMessage back into the packet processing chain
-     * @param sw The switch to use for the message
-     * @param msg the message to inject
-     * @param bContext a floodlight context to use if required. Can be null
-     * @return True if successfully re-injected, false otherwise
-     * @throws NullPointerException if switch or msg is null
-     */
-    public boolean injectOfMessage(IOFSwitch sw, OFMessage msg,
-            FloodlightContext bContext);
-
     /**
      * Process written messages through the message listeners for the controller
      * @param sw The switch being written to
      * @param m the message
-     * @param bc any accompanying context object. Can be null in which case a
-     * new context will be allocated and passed to listeners
      * @throws NullPointerException if switch or msg is null
      */
-    public void handleOutgoingMessage(IOFSwitch sw, OFMessage m,
-            FloodlightContext bc);
-
-    /**
-     * Gets the BasicFactory
-     * @return an OpenFlow message factory
-     */
-    public BasicFactory getOFMessageFactory();
+    public void handleOutgoingMessage(IOFSwitch sw, OFMessage m);
 
     /**
      * Run the main I/O loop of the Controller.
@@ -265,21 +187,12 @@ public interface IFloodlightProviderService extends
     */
    public Map<String, Object> getControllerInfo(String type);
 
-
    /**
     * Return the controller start time in  milliseconds
     * @return
     */
    public long getSystemStartTime();
 
-   /**
-    * Configure controller to always clear the flow table on the switch,
-    * when it connects to controller. This will be true for first time switch
-    * reconnect, as well as a switch re-attaching to Controller after HA
-    * switch over to ACTIVE role
-    */
-   public void setAlwaysClearFlowsOnSwActivate(boolean value);
-
    /**
     * Get controller memory information
     */
@@ -292,30 +205,38 @@ public interface IFloodlightProviderService extends
    public Long getUptime();
 
    /**
-    * Adds an OFSwitch driver
-    *  @param manufacturerDescriptionPrefix Register the given prefix
-    * with the driver.
-    * @param driver A IOFSwitchDriver instance to handle IOFSwitch instaniation
-    * for the given manufacturer description prefix
-    * @throws IllegalStateException If the the manufacturer description is
-    * already registered
-    * @throws NullPointerExeption if manufacturerDescriptionPrefix is null
-    * @throws NullPointerExeption if driver is null
+    * Get the set of port prefixes that will define an UPLINK port.
+    * @return The set of prefixes
     */
-   public void addOFSwitchDriver(String desc, IOFSwitchDriver driver);
+   public Set<String> getUplinkPortPrefixSet();
+
+
+   public void handleMessage(IOFSwitch sw, OFMessage m,
+                          FloodlightContext bContext);
 
    /**
-    * Record a switch event in in-memory debug-event
-    * @param switchDPID
-    * @param reason Reason for this event
-    * @param flushNow see debug-event flushing in IDebugEventService
+    * Gets a hash wheeled timer to be used for for timeout scheduling
+    * @return a hash wheeled timer
     */
-   public void addSwitchEvent(long switchDPID, String reason, boolean flushNow);
+   public Timer getTimer();
 
    /**
-    * Get the set of port prefixes that will define an UPLINK port.
-    * @return The set of prefixes
+    * Gets the role manager
+    * @return the role manager
     */
-   public Set<String> getUplinkPortPrefixSet();
+   public RoleManager getRoleManager();
+
+   /**
+    * Gets the current module loading state.
+    * @return the current module loading state.
+    */
+   ModuleLoaderState getModuleLoaderState();
+
+   /**
+    * Gets the current number of worker threads
+    * @return Used for netty setup
+    */
+   public int getWorkerThreads();
 
 }
+
diff --git a/src/main/java/net/floodlightcontroller/core/IHAListener.java b/src/main/java/net/floodlightcontroller/core/IHAListener.java
deleted file mode 100644
index 2ffe82fd5..000000000
--- a/src/main/java/net/floodlightcontroller/core/IHAListener.java
+++ /dev/null
@@ -1,45 +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.core;
-
-import java.util.Map;
-
-public interface IHAListener extends IListener<HAListenerTypeMarker> {
-
-    /**
-     * This notification is fired if the controller's initial role was SLAVE
-     * and the controller is now transitioning to MASTER.
-     * Modules need to read their initial role in startUp from floodlight
-     * provider.
-     */
-    public void transitionToMaster();
-
-    /**
-     * Gets called when the IP addresses of the controller nodes in the
-     * controller cluster change. All parameters map controller ID to
-     * the controller's IP.
-     *
-     * @param curControllerNodeIPs The current mapping of controller IDs to IP
-     * @param addedControllerNodeIPs These IPs were added since the last update
-     * @param removedControllerNodeIPs These IPs were removed since the last update
-     */
-    public void controllerNodeIPsChanged(
-            Map<String, String> curControllerNodeIPs,
-            Map<String, String> addedControllerNodeIPs,
-            Map<String, String> removedControllerNodeIPs
-            );
-}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFConnection.java b/src/main/java/net/floodlightcontroller/core/IOFConnection.java
new file mode 100644
index 000000000..a14021fbd
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/IOFConnection.java
@@ -0,0 +1,62 @@
+package net.floodlightcontroller.core;
+
+import java.net.SocketAddress;
+
+import java.util.Date;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFAuxId;
+
+
+/** Contract for an openflow connection to a switch.
+ *  Provides message write and request/response handling capabilities.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public interface IOFConnection extends IOFMessageWriter {
+
+    /**
+     * Retrieves the date the connection connected to this controller
+     * @return the date
+     */
+    Date getConnectedSince();
+
+    /**
+     * Flush all flows queued for this switch in the current thread.
+     * NOTE: The contract is limited to the current thread
+     */
+    void flush();
+
+    /** @return the DatapathId of the switch associated with the connection */
+    DatapathId getDatapathId();
+
+    /** @return the OFAuxId of the this connection */
+    OFAuxId getAuxId();
+
+    /**
+    * Get the IP address of the remote (switch) end of the connection
+    * @return the inet address
+    */
+    SocketAddress getRemoteInetAddress();
+
+    /**
+     * Get the IP address of the local end of the connection
+     *
+     * @return the inet address
+     */
+    SocketAddress getLocalInetAddress();
+
+    /**
+     * Get's the OFFactory that this connection was constructed with.
+     * This is the factory that was found in the features reply during
+     * the channel handshake
+     * @return The connection's OFFactory
+     */
+    OFFactory getOFFactory();
+
+    /** @return whether this connection is currently (still) connected to the controller.
+     */
+    boolean isConnected();
+
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFConnectionBackend.java b/src/main/java/net/floodlightcontroller/core/IOFConnectionBackend.java
new file mode 100644
index 000000000..0ec7a9e1b
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/IOFConnectionBackend.java
@@ -0,0 +1,23 @@
+package net.floodlightcontroller.core;
+
+import net.floodlightcontroller.core.internal.IOFConnectionListener;
+
+public interface IOFConnectionBackend extends IOFConnection {
+    /**
+     * Disconnect the channel
+     */
+    void disconnect();
+
+    /**
+     * Cancel all pending request
+     */
+    void cancelAllPendingRequests();
+
+    /** @return whether the output stream associated with this connection
+     *  is currently writeable (for throttling)
+     */
+    boolean isWritable();
+
+    /** set the message/closing listener for this connection */
+    void setListener(IOFConnectionListener listener);
+}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFMessageListener.java b/src/main/java/net/floodlightcontroller/core/IOFMessageListener.java
index 00fdac1f9..1fe71529c 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFMessageListener.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFMessageListener.java
@@ -17,8 +17,8 @@
 
 package net.floodlightcontroller.core;
 
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
 
 /**
  *
diff --git a/src/main/java/net/floodlightcontroller/core/IOFMessageWriter.java b/src/main/java/net/floodlightcontroller/core/IOFMessageWriter.java
new file mode 100644
index 000000000..bd27181f1
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/IOFMessageWriter.java
@@ -0,0 +1,79 @@
+/**
+*    Copyright 2011, Big Switch Networks, Inc.
+*    Originally created by David Erickson, Stanford University
+*
+*    Licensed under the Apache License, Version 2.0 (the "License"); you may
+*    not use this file except in compliance with the License. You may obtain
+*    a copy of the License at
+*
+*         http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+*    License for the specific language governing permissions and limitations
+*    under the License.
+**/
+
+package net.floodlightcontroller.core;
+
+import java.util.List;
+
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFRequest;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * An interface to describe classes that write OF messages.
+ * E.g. IOFSwitch, IOFConnection
+ */
+
+public interface IOFMessageWriter{
+
+    /**
+     * Writes to the OFMessage to the output stream.
+     *
+     * <p><b>Note:</b> this method has fire-and-forget semantics. When the connection is
+     * not currently connected, it will silently discard the messages.
+     *
+     * @param m
+     */
+    void write(OFMessage m);
+
+    /**
+     * Writes the list of messages to the output stream.
+     *
+     * <p><b>Note:</b> this method has fire-and-forget semantics. When the connection is
+     * not currently connected, it will silently discard the messages.
+     *
+     * @param msglist
+     */
+    void write(Iterable<OFMessage> msglist);
+    
+    /** write an OpenFlow Request message, register for a single corresponding reply message
+     *  or error message.
+     *
+     * @param request
+     * @return a Future object that can be used to retrieve the asynchrounous
+     *         response when available.
+     *
+     *         If the connection is not currently connected, will
+     *         return a Future that immediately fails with a @link{SwitchDisconnectedException}.
+     */
+    <R extends OFMessage> ListenableFuture<R> writeRequest(OFRequest<R> request);
+
+    /** write a Stats (Multipart-) request, register for all corresponding reply messages.
+     * Returns a Future object that can be used to retrieve the List of asynchronous
+     * OFStatsReply messages when it is available.
+     *
+     * @param request stats request
+     * @return Future object wrapping OFStatsReply
+     *         If the connection is not currently connected, will
+     *         return a Future that immediately fails with a @link{SwitchDisconnectedException}.
+     */
+    <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest(
+            OFStatsRequest<REPLY> request);
+}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
deleted file mode 100644
index fb2746040..000000000
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
+++ /dev/null
@@ -1,669 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc.
-*    Originally created by David Erickson, Stanford University
-*
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core;
-
-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.concurrent.Future;
-import net.floodlightcontroller.core.IFloodlightProviderService.Role;
-import net.floodlightcontroller.core.internal.Controller;
-import net.floodlightcontroller.debugcounter.IDebugCounterService;
-import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-import net.floodlightcontroller.util.OrderedCollection;
-
-import org.jboss.netty.channel.Channel;
-import org.openflow.protocol.OFFeaturesReply;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPortStatus;
-import org.openflow.protocol.OFStatisticsReply;
-import org.openflow.protocol.OFStatisticsRequest;
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
-import org.openflow.protocol.statistics.OFStatistics;
-
-/**
- *
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public interface IOFSwitch {
-    // Attribute keys
-    public static final String SWITCH_DESCRIPTION_FUTURE = "DescriptionFuture";
-    public static final String SWITCH_SUPPORTS_NX_ROLE = "supportsNxRole";
-    public static final String SWITCH_IS_CORE_SWITCH = "isCoreSwitch";
-    public static final String PROP_FASTWILDCARDS = "FastWildcards";
-    public static final String PROP_REQUIRES_L3_MATCH = "requiresL3Match";
-    public static final String PROP_SUPPORTS_OFPP_TABLE = "supportsOfppTable";
-    public static final String PROP_SUPPORTS_OFPP_FLOOD = "supportsOfppFlood";
-    public static final String PROP_SUPPORTS_NETMASK_TBL = "supportsNetmaskTbl";
-
-    public enum OFPortType {
-        NORMAL("normal"),         // normal port (default)
-        TUNNEL("tunnel"),         // tunnel port
-        UPLINK("uplink"),         // uplink port (on a virtual switch)
-        MANAGEMENT("management"), // for in-band management
-        TUNNEL_LOOPBACK("tunnel-loopback");
-
-        private final String value;
-        OFPortType(String v) {
-            value = v;
-        }
-
-        @Override
-        public String toString() {
-            return value;
-        }
-
-        public static OFPortType fromString(String str) {
-            for (OFPortType m : OFPortType.values()) {
-                if (m.value.equals(str)) {
-                    return m;
-                }
-            }
-            return OFPortType.NORMAL;
-        }
-    }
-
-    /**
-     * Describes a change of an open flow port
-     */
-    public static class PortChangeEvent {
-        public final ImmutablePort port;
-        public final PortChangeType type;
-        /**
-         * @param port
-         * @param type
-         */
-        public PortChangeEvent(ImmutablePort port,
-                               PortChangeType type) {
-            this.port = port;
-            this.type = type;
-        }
-        /* (non-Javadoc)
-         * @see java.lang.Object#hashCode()
-         */
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((port == null) ? 0 : port.hashCode());
-            result = prime * result + ((type == null) ? 0 : type.hashCode());
-            return result;
-        }
-        /* (non-Javadoc)
-         * @see java.lang.Object#equals(java.lang.Object)
-         */
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj) return true;
-            if (obj == null) return false;
-            if (getClass() != obj.getClass()) return false;
-            PortChangeEvent other = (PortChangeEvent) obj;
-            if (port == null) {
-                if (other.port != null) return false;
-            } else if (!port.equals(other.port)) return false;
-            if (type != other.type) return false;
-            return true;
-        }
-        /* (non-Javadoc)
-         * @see java.lang.Object#toString()
-         */
-        @Override
-        public String toString() {
-            return "[" + type + " " + port.toBriefString() + "]";
-        }
-    }
-
-    /**
-     * the type of change that happened to an open flow port
-     */
-    public enum PortChangeType {
-        ADD, OTHER_UPDATE, DELETE, UP, DOWN,
-    }
-
-    /**
-     * Set IFloodlightProviderService for this switch instance
-     * Called immediately after instantiation
-     *
-     * @param controller
-     */
-    public void setFloodlightProvider(Controller controller);
-
-    /**
-     * Set IThreadPoolService for this switch instance
-     * Called immediately after instantiation
-     *
-     * @param threadPool
-     */
-    public void setThreadPoolService(IThreadPoolService threadPool);
-
-    /**
-     * Set debug counter service for per-switch counters
-     * Called immediately after instantiation
-     * @param debugCounters
-     * @throws CounterException
-     */
-    public void setDebugCounterService(IDebugCounterService debugCounters)
-            throws CounterException;
-
-    /**
-     * Set the netty Channel this switch instance is associated with
-     * Called immediately after instantiation
-     *
-     * @param channel
-     */
-    public void setChannel(Channel channel);
-
-    /**
-     * Called when OFMessage enters pipeline. Returning true cause the message
-     * to be dropped.
-     * @param ofm
-     * @return
-     */
-    public boolean inputThrottled(OFMessage ofm);
-
-    /**
-     * Return if the switch is currently overloaded. The definition of
-     * overload refers to excessive traffic in the control path, namely
-     * a high packet in rate.
-     * @return
-     */
-    boolean isOverloaded();
-
-    /**
-     * Write OFMessage to the output stream, subject to switch rate limiting.
-     * The message will be handed to the floodlightProvider for possible filtering
-     * and processing by message listeners
-     * @param msg
-     * @param cntx
-     * @throws IOException
-     */
-    public void writeThrottled(OFMessage msg, FloodlightContext cntx) throws IOException;
-
-    /**
-     * Writes the list of messages to the output stream, subject to rate limiting.
-     * The message will be handed to the floodlightProvider for possible filtering
-     * and processing by message listeners.
-     * @param msglist
-     * @param bc
-     * @throws IOException
-     */
-    void writeThrottled(List<OFMessage> msglist, FloodlightContext bc)
-            throws IOException;
-
-    /**
-     * Writes to the OFMessage to the output stream, bypassing rate limiting.
-     * The message will be handed to the floodlightProvider for possible filtering
-     * and processing by message listeners
-     * @param m
-     * @param bc
-     * @throws IOException
-     */
-    public void write(OFMessage m, FloodlightContext bc) throws IOException;
-
-    /**
-     * Writes the list of messages to the output stream, bypassing rate limiting.
-     * The message will be handed to the floodlightProvider for possible filtering
-     * and processing by message listeners.
-     * @param msglist
-     * @param bc
-     * @throws IOException
-     */
-    public void write(List<OFMessage> msglist, FloodlightContext bc) throws IOException;
-
-    /**
-     *
-     * @throws IOException
-     */
-    public void disconnectOutputStream();
-
-    /**
-     * Returns switch features from features Reply
-     * @return
-     */
-    public int getBuffers();
-
-    public int getActions();
-
-    public int getCapabilities();
-
-    public byte getTables();
-
-    /**
-     * @return a copy of the description statistics for this switch
-     */
-    public OFDescriptionStatistics getDescriptionStatistics();
-
-    /**
-     * Set the OFFeaturesReply message returned by the switch during initial
-     * handshake.
-     * @param featuresReply
-     */
-    public void setFeaturesReply(OFFeaturesReply featuresReply);
-
-    /**
-     * Get list of all enabled ports. This will typically be different from
-     * the list of ports in the OFFeaturesReply, since that one is a static
-     * snapshot of the ports at the time the switch connected to the controller
-     * whereas this port list also reflects the port status messages that have
-     * been received.
-     * @return Unmodifiable list of ports not backed by the underlying collection
-     */
-    public Collection<ImmutablePort> getEnabledPorts();
-
-    /**
-     * Get list of the port numbers of all enabled ports. This will typically
-     * be different from the list of ports in the OFFeaturesReply, since that
-     * one is a static snapshot of the ports at the time the switch connected
-     * to the controller whereas this port list also reflects the port status
-     * messages that have been received.
-     * @return Unmodifiable list of ports not backed by the underlying collection
-     */
-    public Collection<Short> getEnabledPortNumbers();
-
-    /**
-     * Retrieve the port object by the port number. The port object
-     * is the one that reflects the port status updates that have been
-     * received, not the one from the features reply.
-     * @param portNumber
-     * @return port object
-     */
-    public ImmutablePort getPort(short portNumber);
-
-    /**
-     * Retrieve the port object by the port name. The port object
-     * is the one that reflects the port status updates that have been
-     * received, not the one from the features reply.
-     * Port names are case insentive
-     * @param portName
-     * @return port object
-     */
-    public ImmutablePort getPort(String portName);
-
-    /**
-     * Add or modify a switch port.
-     * This is called by the core controller
-     * code in response to a OFPortStatus message. It should not typically be
-     * called by other floodlight applications.
-     *
-     * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow
-     * spec is not clear on whether portNames are portNumbers are considered
-     * authoritative identifiers. We treat portNames <-> portNumber mappings
-     * as fixed. If they change, we delete all previous conflicting ports and
-     * add all new ports.
-     *
-     * @param ps the port status message
-     * @return the ordered Collection of changes "applied" to the old ports
-     * of the switch according to the PortStatus message. A single PortStatus
-     * message can result in multiple changes.
-     * If portName <-> portNumber mappings have
-     * changed, the iteration order ensures that delete events for old
-     * conflicting appear before before events adding new ports
-     */
-    public OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps);
-
-    /**
-     * Get list of all ports. This will typically be different from
-     * the list of ports in the OFFeaturesReply, since that one is a static
-     * snapshot of the ports at the time the switch connected to the controller
-     * whereas this port list also reflects the port status messages that have
-     * been received.
-     * @return Unmodifiable list of ports
-     */
-    public Collection<ImmutablePort> getPorts();
-
-    /**
-     * @param portNumber
-     * @return Whether a port is enabled per latest port status message
-     * (not configured down nor link down nor in spanning tree blocking state)
-     */
-    public boolean portEnabled(short portNumber);
-
-    /**
-     * @param portNumber
-     * @return Whether a port is enabled per latest port status message
-     * (not configured down nor link down nor in spanning tree blocking state)
-     */
-    public boolean portEnabled(String portName);
-
-    /**
-     * Compute the changes that would be required to replace the old ports
-     * of this switch with the new ports
-     * @param ports new ports to set
-     * @return the ordered collection of changes "applied" to the old ports
-     * of the switch in order to set them to the new set.
-     * If portName <-> portNumber mappings have
-     * changed, the iteration order ensures that delete events for old
-     * conflicting appear before before events adding new ports
-     */
-    public OrderedCollection<PortChangeEvent>
-            comparePorts(Collection<ImmutablePort> ports);
-
-    /**
-     * Replace the ports of this switch with the given ports.
-     * @param ports new ports to set
-     * @return the ordered collection of changes "applied" to the old ports
-     * of the switch in order to set them to the new set.
-     * If portName <-> portNumber mappings have
-     * changed, the iteration order ensures that delete events for old
-     * conflicting appear before before events adding new ports
-     */
-    public OrderedCollection<PortChangeEvent>
-            setPorts(Collection<ImmutablePort> ports);
-
-
-    /**
-     * Get the datapathId of the switch
-     * @return
-     */
-    public long getId();
-
-    /**
-     * Get a string version of the ID for this switch
-     * @return
-     */
-    public String getStringId();
-
-    /**
-     * Get the IP Address for the switch
-     * @return the inet address
-     */
-    public SocketAddress getInetAddress();
-
-    /**
-     * Retrieves attributes of this switch
-     * @return
-     */
-    public Map<Object, Object> getAttributes();
-
-    /**
-     * Retrieves the date the switch connected to this controller
-     * @return the date
-     */
-    public Date getConnectedSince();
-
-    /**
-     * Returns the next available transaction id
-     * @return
-     */
-    public int getNextTransactionId();
-
-    /**
-     * Returns a Future object that can be used to retrieve the asynchronous
-     * OFStatisticsReply when it is available.
-     *
-     * @param request statistics request
-     * @return Future object wrapping OFStatisticsReply
-     * @throws IOException
-     */
-    public Future<List<OFStatistics>> queryStatistics(OFStatisticsRequest request)
-
-            throws IOException;
-
-    /**
-     * Returns a Future object that can be used to retrieve the asynchronous
-     * OFStatisticsReply when it is available.
-     *
-     * @param request statistics request
-     * @return Future object wrapping OFStatisticsReply
-     * @throws IOException
-     */
-    public Future<OFFeaturesReply> querySwitchFeaturesReply()
-            throws IOException;
-
-    /**
-     * Deliver the featuresReply future reply
-     * @param reply the reply to deliver
-     */
-    void deliverOFFeaturesReply(OFMessage reply);
-
-    /*
-     * Cancel features reply with a specific transction ID
-     * @param transactionId the transaction ID
-     */
-    public void cancelFeaturesReply(int transactionId);
-
-    /**
-     * Check if the switch is connected to this controller. Whether a switch
-     * is connected is independent of whether the switch is active
-     * @return whether the switch is still disconnected
-     */
-    public boolean isConnected();
-
-    /**
-     * Check if the switch is active. I.e., the switch is connected to this
-     * controller and is in master role
-     * @return
-     */
-    public boolean isActive();
-
-    /**
-     * Set whether the switch is connected
-     * @param connected whether the switch is connected
-     */
-    public void setConnected(boolean connected);
-
-    /**
-     * Get the current role of the controller for the switch
-     * @return the role of the controller
-     */
-    public Role getHARole();
-
-    /**
-     * Set switch's HA role to role. The haRoleReplyReceived indicates
-     * if a reply was received from the switch (error replies excluded).
-     *
-     * If role is null, the switch should close the channel connection.
-     *
-     * @param role
-     * @param haRoleReplyReceived
-     */
-    public void setHARole(Role role);
-
-    /**
-     * Deliver the statistics future reply
-     * @param reply the reply to deliver
-     */
-    public void deliverStatisticsReply(OFStatisticsReply reply);
-
-    /**
-     * Cancel the statistics reply with the given transaction ID
-     * @param transactionId the transaction ID
-     */
-    public void cancelStatisticsReply(int transactionId);
-
-    /**
-     * Cancel all statistics replies
-     */
-    public void cancelAllStatisticsReplies();
-
-    /**
-     * Checks if a specific switch property exists for this switch
-     * @param name name of property
-     * @return value for name
-     */
-    boolean hasAttribute(String name);
-
-    /**
-     * Set properties for switch specific behavior
-     * @param name name of property
-     * @return value for name
-     */
-    Object getAttribute(String name);
-
-    /**
-     * Check if the given attribute is present and if so whether it is equal
-     * to "other"
-     * @param name the name of the attribute to check
-     * @param other the object to compare the attribute against.
-     * @return true iff the specified attribute is set and equals() the given
-     * other object.
-     */
-    boolean attributeEquals(String name, Object other);
-
-    /**
-     * Set properties for switch specific behavior
-     * @param name name of property
-     * @param value value for name
-     */
-    void setAttribute(String name, Object value);
-
-    /**
-     * Set properties for switch specific behavior
-     * @param name name of property
-     * @return current value for name or null (if not present)
-     */
-    Object removeAttribute(String name);
-
-    /**
-     * Clear all flowmods on this switch
-     */
-    public void clearAllFlowMods();
-
-    /**
-     * Update broadcast cache
-     * @param data
-     * @return true if there is a cache hit
-     *         false if there is no cache hit.
-     */
-    public boolean updateBroadcastCache(Long entry, Short port);
-
-    /**
-     * Get the portBroadcastCacheHits
-     * @return
-     */
-    public Map<Short, Long> getPortBroadcastHits();
-
-    /**
-     * Send a flow statistics request to the switch. This call returns after
-     * sending the stats. request to the switch.
-     * @param request flow statistics request message
-     * @param xid transaction id, must be obtained by using the getXid() API.
-     * @param caller the caller of the API. receive() callback of this
-     * caller would be called when the reply from the switch is received.
-     * @return the transaction id for the message sent to the switch. The
-     * transaction id can be used to match the response with the request. Note
-     * that the transaction id is unique only within the scope of this switch.
-     * @throws IOException
-     */
-    public void sendStatsQuery(OFStatisticsRequest request, int xid,
-                            IOFMessageListener caller) throws IOException;
-
-    /**
-     * Flush all flows queued for this switch in the current thread.
-     * NOTE: The contract is limited to the current thread
-     */
-    public void flush();
-
-    /***********************************************
-     * The following method can be overridden by
-     * specific types of switches
-     ***********************************************
-     */
-
-    /**
-     * Set the SwitchProperties based on it's description
-     * @param description
-     */
-    public void setSwitchProperties(OFDescriptionStatistics description);
-
-    /**
-     * Return the type of OFPort
-     * @param port_num
-     * @return
-     */
-    public OFPortType getPortType(short port_num);
-
-    /**
-     * Can the port be turned on without forming a new loop?
-     * @param port_num
-     * @return
-     */
-    public boolean isFastPort(short port_num);
-
-    /**
-     * Return whether write throttling is enabled on the switch
-     */
-    public boolean isWriteThrottleEnabled();
-
-    /**
-     * Set the flow table full flag in the switch
-     */
-    public void setTableFull(boolean isFull);
-
-    /**
-     * Set the suggested priority to use when installing access flows in
-     * this switch.
-     */
-    public void setAccessFlowPriority(short prio);
-
-    /**
-     * Set the suggested priority to use when installing core flows in
-     * this switch.
-     */
-    public void setCoreFlowPriority(short prio);
-
-    /**
-     * Get the suggested priority to use when installing access flows in
-     * this switch.
-     */
-    public short getAccessFlowPriority();
-
-    /**
-     * Get the suggested priority to use when installing core flows in
-     * this switch.
-     */
-    public short getCoreFlowPriority();
-
-    /**
-     * Start this switch driver's sub handshake. This might be a no-op but
-     * this method must be called at least once for the switch to be become
-     * ready.
-     * This method must only be called from the I/O thread
-     * @throws SwitchDriverSubHandshakeAlreadyStarted if the sub-handshake has
-     * already been started
-     */
-    public void startDriverHandshake();
-
-    /**
-     * Check if the sub-handshake for this switch driver has been completed.
-     * This method can only be called after startDriverHandshake()
-     *
-     * This methods must only be called from the I/O thread
-     * @return true if the sub-handshake has been completed. False otherwise
-     * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has
-     * not been called yet.
-     */
-    public boolean isDriverHandshakeComplete();
-
-    /**
-     * Pass the given OFMessage to the driver as part of this driver's
-     * sub-handshake. Must not be called after the handshake has been completed
-     * This methods must only be called from the I/O thread
-     * @param m The message that the driver should process
-     * @throws SwitchDriverSubHandshakeCompleted if isDriverHandshake() returns
-     * false before this method call
-     * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has
-     * not been called yet.
-     */
-    public void processDriverHandshakeMessage(OFMessage m);
-}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
new file mode 100644
index 000000000..58cc62786
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchBackend.java
@@ -0,0 +1,189 @@
+/**
+*    Copyright 2011, Big Switch Networks, Inc.
+*    Originally created by David Erickson, Stanford University
+*
+*    Licensed under the Apache License, Version 2.0 (the "License"); you may
+*    not use this file except in compliance with the License. You may obtain
+*    a copy of the License at
+*
+*         http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+*    License for the specific language governing permissions and limitations
+*    under the License.
+**/
+
+package net.floodlightcontroller.core;
+
+import java.util.Collection;
+
+import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsReply;
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
+
+import net.floodlightcontroller.util.OrderedCollection;
+
+/**
+ * An openflow switch connecting to the controller.  This interface offers
+ * methods for interacting with switches using OpenFlow, and retrieving
+ * information about the switches.
+ */
+public interface IOFSwitchBackend extends IOFSwitch {
+    /**
+     * Set the netty Channel this switch instance is associated with
+     * Called immediately after instantiation
+     * @param channel
+     */
+    void registerConnection(IOFConnectionBackend connection);
+
+    /**
+     * Remove the netty Channels associated with this switch
+     * @param channel
+     */
+    void removeConnections();
+
+    /**
+     * Remove the netty Channel belonging to the specified connection
+     * @param connection
+     */
+    void removeConnection(IOFConnectionBackend connection);
+
+    /**
+     * Set the OFFeaturesReply message returned by the switch during initial
+     * handshake.
+     * @param featuresReply
+     */
+    void setFeaturesReply(OFFeaturesReply featuresReply);
+
+    /** set the gentable mapping for this switch */
+    void setGenTableMap(GenTableMap map);
+
+    /**
+     * Add or modify a switch port.
+     * This is called by the core controller
+     * code in response to a OFPortStatus message. It should not typically be
+     * called by other floodlight applications.
+     *
+     * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow
+     * spec is not clear on whether portNames are portNumbers are considered
+     * authoritative identifiers. We treat portNames <-> portNumber mappings
+     * as fixed. If they change, we delete all previous conflicting ports and
+     * add all new ports.
+     *
+     * @param ps the port status message
+     * @return the ordered Collection of changes "applied" to the old ports
+     * of the switch according to the PortStatus message. A single PortStatus
+     * message can result in multiple changes.
+     * If portName <-> portNumber mappings have
+     * changed, the iteration order ensures that delete events for old
+     * conflicting appear before before events adding new ports
+     */
+    OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps);
+
+    /**
+     * Compute the changes that would be required to replace the old ports
+     * of this switch with the new ports
+     * @param ports new ports to set
+     * @return the ordered collection of changes "applied" to the old ports
+     * of the switch in order to set them to the new set.
+     * If portName <-> portNumber mappings have
+     * changed, the iteration order ensures that delete events for old
+     * conflicting appear before before events adding new ports
+     */
+    OrderedCollection<PortChangeEvent>
+            comparePorts(Collection<OFPortDesc> ports);
+
+    /**
+     * Replace the ports of this switch with the given ports.
+     * @param ports new ports to set
+     * @return the ordered collection of changes "applied" to the old ports
+     * of the switch in order to set them to the new set.
+     * If portName <-> portNumber mappings have
+     * changed, the iteration order ensures that delete events for old
+     * conflicting appear before before events adding new ports
+     */
+    OrderedCollection<PortChangeEvent>
+            setPorts(Collection<OFPortDesc> ports);
+
+    /***********************************************
+     * The following method can be overridden by
+     * specific types of switches
+     ***********************************************
+     */
+
+    /**
+     * Set the SwitchProperties based on it's description
+     * @param description
+     */
+    void setSwitchProperties(SwitchDescription description);
+
+    /**
+     * Set the flow table full flag in the switch
+     */
+    void setTableFull(boolean isFull);
+
+    /**
+     * Start this switch driver's sub handshake. This might be a no-op but
+     * this method must be called at least once for the switch to be become
+     * ready.
+     * This method must only be called from the I/O thread
+     * @throws SwitchDriverSubHandshakeAlreadyStarted if the sub-handshake has
+     * already been started
+     */
+    void startDriverHandshake();
+
+    /**
+     * Check if the sub-handshake for this switch driver has been completed.
+     * This method can only be called after startDriverHandshake()
+     *
+     * This methods must only be called from the I/O thread
+     * @return true if the sub-handshake has been completed. False otherwise
+     * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has
+     * not been called yet.
+     */
+    boolean isDriverHandshakeComplete();
+
+    /**
+     * Pass the given OFMessage to the driver as part of this driver's
+     * sub-handshake. Must not be called after the handshake has been completed
+     * This methods must only be called from the I/O thread
+     * @param m The message that the driver should process
+     * @throws SwitchDriverSubHandshakeCompleted if isDriverHandshake() returns
+     * false before this method call
+     * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has
+     * not been called yet.
+     */
+    void processDriverHandshakeMessage(OFMessage m);
+
+    void setPortDescStats(OFPortDescStatsReply portDescStats);
+
+    /**
+     * Cancel all pending request
+     */
+    void cancelAllPendingRequests();
+
+    /** the the current HA role of this switch */
+    void setControllerRole(OFControllerRole role);
+
+    void setStatus(SwitchStatus switchStatus);
+
+    /**
+     * Updates the switch's mapping of controller connections
+     * @param controllerCxnsReply the controller connections message sent from the switch
+     */
+    void updateControllerConnections(OFBsnControllerConnectionsReply controllerCxnsReply);
+
+    /**
+     * Determines whether there is another master controller that the switches are
+     * connected to by looking at the controller connections.
+     * @return true if another viable master exists
+     */
+    boolean hasAnotherMaster();
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchDriver.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchDriver.java
index f7f720f91..b56655535 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitchDriver.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchDriver.java
@@ -16,7 +16,10 @@
 
 package net.floodlightcontroller.core;
 
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
+import net.floodlightcontroller.core.IOFSwitchBackend;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+
+import net.floodlightcontroller.core.SwitchDescription;
 
 public interface IOFSwitchDriver {
     /**
@@ -26,5 +29,5 @@ public interface IOFSwitchDriver {
      * @return A IOFSwitch instance if the driver found an implementation
      * for the given description. Null otherwise
      */
-    public IOFSwitch getOFSwitchImpl(OFDescriptionStatistics description);
-}
+    public IOFSwitchBackend getOFSwitchImpl(SwitchDescription description, OFFactory factory);
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java b/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java
index e0c7b53f8..57eb4d179 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitchListener.java
@@ -17,6 +17,9 @@
 
 package net.floodlightcontroller.core;
 
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.types.DatapathId;
+
 /**
  * Switch lifecycle notifications.
  *
@@ -45,20 +48,20 @@ public interface IOFSwitchListener {
      * the switch is connected at some controller in the cluster
      * @param switchId the datapath Id of the new switch
      */
-    public void switchAdded(long switchId);
+    public void switchAdded(DatapathId switchId);
 
     /**
      * Fired when a switch disconnects from the cluster ,
      * @param switchId the datapath Id of the switch
      */
-    public void switchRemoved(long switchId);
+    public void switchRemoved(DatapathId switchId);
 
     /**
      * Fired when a switch becomes active *on the local controller*, I.e.,
      * the switch is connected to the local controller and is in MASTER mode
      * @param switchId the datapath Id of the switch
      */
-    public void switchActivated(long switchId);
+    public void switchActivated(DatapathId switchId);
 
     /**
      * Fired when a port on a known switch changes.
@@ -74,9 +77,9 @@ public interface IOFSwitchListener {
      * @param port
      * @param type
      */
-    public void switchPortChanged(long switchId,
-                                  ImmutablePort port,
-                                  IOFSwitch.PortChangeType type);
+    public void switchPortChanged(DatapathId switchId,
+                                  OFPortDesc port,
+                                  PortChangeType type);
 
     /**
      * Fired when any non-port related information (e.g., attributes,
@@ -84,5 +87,5 @@ public interface IOFSwitchListener {
      * TODO: currently unused
      * @param switchId
      */
-    public void switchChanged(long switchId);
+    public void switchChanged(DatapathId switchId);
 }
diff --git a/src/main/java/net/floodlightcontroller/core/ImmutablePort.java b/src/main/java/net/floodlightcontroller/core/ImmutablePort.java
deleted file mode 100644
index c015454ca..000000000
--- a/src/main/java/net/floodlightcontroller/core/ImmutablePort.java
+++ /dev/null
@@ -1,561 +0,0 @@
-package net.floodlightcontroller.core;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Set;
-
-import net.floodlightcontroller.util.EnumBitmaps;
-import org.openflow.protocol.OFPhysicalPort;
-import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
-import org.openflow.protocol.OFPhysicalPort.OFPortFeatures;
-import org.openflow.protocol.OFPhysicalPort.OFPortState;
-import org.openflow.protocol.OFPhysicalPort.PortSpeed;
-import org.openflow.util.HexString;
-
-
-/**
- * An immutable version of an OFPhysical port. In addition, it uses EnumSets
- * instead of integer bitmaps to represent
- * OFPortConfig, OFPortState, and OFPortFeature bitmaps.
- *
- * Port names are stored with the original case but equals() and XXXX use
- * case-insentivie comparisions for port names!!
- *
- * TODO: create a Builder so we can easily construct OFPhysicalPorts
- * TODO: should we verify / ensure that the features make sense, i.e., that
- *     currentFeatures IsSubsetOf advertisedFeatures IsSubsetOf
- *     supportedFeatures
- *
- * @author gregor
- *
- */
-public class ImmutablePort {
-    private final short portNumber;
-    private final byte[] hardwareAddress;
-    private final String name;
-    private final EnumSet<OFPortConfig> config;
-    private final boolean portStateLinkDown;
-    private final OFPortState stpState;
-    private final EnumSet<OFPortFeatures> currentFeatures;
-    private final EnumSet<OFPortFeatures> advertisedFeatures;
-    private final EnumSet<OFPortFeatures> supportedFeatures;
-    private final EnumSet<OFPortFeatures> peerFeatures;
-
-    /**
-     * A builder class to create ImmutablePort instances
-     *
-     * TODO: add methods to remove elements from the EnumSets
-     */
-    public static class Builder {
-        private short portNumber;
-        private byte[] hardwareAddress;
-        private String name;
-        private EnumSet<OFPortConfig> config;
-        private boolean portStateLinkDown;
-        private OFPortState stpState;
-        private EnumSet<OFPortFeatures> currentFeatures;
-        private EnumSet<OFPortFeatures> advertisedFeatures;
-        private EnumSet<OFPortFeatures> supportedFeatures;
-        private EnumSet<OFPortFeatures> peerFeatures;
-
-        public Builder() {
-            this.portNumber = (short)1;
-            this.hardwareAddress = new byte[] { 0, 0, 0, 0, 0, 0 };
-            this.name = "";
-            this.config = EnumSet.noneOf(OFPortConfig.class);
-            this.portStateLinkDown = false;
-            this.stpState = OFPortState.OFPPS_STP_LISTEN;
-            this.currentFeatures = EnumSet.noneOf(OFPortFeatures.class);
-            this.advertisedFeatures = EnumSet.noneOf(OFPortFeatures.class);
-            this.supportedFeatures = EnumSet.noneOf(OFPortFeatures.class);
-            this.peerFeatures = EnumSet.noneOf(OFPortFeatures.class);
-        }
-
-        public Builder(ImmutablePort p) {
-            this.portNumber = p.getPortNumber();
-            this.hardwareAddress = p.getHardwareAddress();
-            this.name = p.getName();
-            this.config = EnumSet.copyOf(p.getConfig());
-            this.portStateLinkDown = p.isLinkDown();
-            this.stpState = p.getStpState();
-            this.currentFeatures = EnumSet.copyOf(p.getCurrentFeatures());
-            this.advertisedFeatures = EnumSet.copyOf(p.getAdvertisedFeatures());
-            this.supportedFeatures = EnumSet.copyOf(p.getSupportedFeatures());
-            this.peerFeatures = EnumSet.copyOf(p.getPeerFeatures());
-        }
-
-        /**
-         * @param portNumber the portNumber to set
-         */
-        public Builder setPortNumber(short portNumber) {
-            this.portNumber = portNumber;
-            return this;
-        }
-        /**
-         * @param hardwareAddress the hardwareAddress to set
-         */
-        public Builder setHardwareAddress(byte[] hardwareAddress) {
-            if (hardwareAddress== null)  {
-                throw new NullPointerException("Hardware address must not be null");
-            }
-            if (hardwareAddress.length != 6) {
-                throw new IllegalArgumentException("Harware address must be 6 " +
-                        "bytes long but hardware address is " +
-                        Arrays.toString(hardwareAddress));
-            }
-            this.hardwareAddress = Arrays.copyOf(hardwareAddress, 6);
-            return this;
-        }
-        /**
-         * @param name the name to set
-         */
-        public Builder setName(String name) {
-            if (name == null)
-                throw new NullPointerException("Port name must not be null");
-            this.name = name;
-            return this;
-        }
-        /**
-         * @param config the config to set
-         */
-        public Builder addConfig(OFPortConfig config) {
-            if (config == null)
-                throw new NullPointerException("PortConfig must not be null");
-            this.config.add(config);
-            return this;
-        }
-        /**
-         * @param portStateLinkDown the portStateLinkDown to set
-         */
-        public Builder setPortStateLinkDown(boolean portStateLinkDown) {
-            this.portStateLinkDown = portStateLinkDown;
-            return this;
-        }
-        /**
-         * @param stpState the stpState to set
-         */
-        public Builder setStpState(OFPortState stpState) {
-            if (stpState == null)
-                throw new NullPointerException("stpState must not be null");
-            if (!stpState.isStpState()) {
-                String msg = String.format("OFPortState enum constant %s " +
-                        "is not an STP state", stpState);
-                throw new IllegalArgumentException(msg);
-            }
-            this.stpState = stpState;
-            return this;
-        }
-        /**
-         * @param currentFeatures the currentFeatures to set
-         */
-        public Builder addCurrentFeature(OFPortFeatures currentFeature) {
-            if (currentFeature == null)
-                throw new NullPointerException("CurrentFeature must not be null");
-            this.currentFeatures.add(currentFeature);
-            return this;
-        }
-        /**
-         * @param advertisedFeatures the advertisedFeatures to set
-         */
-        public Builder
-                addAdvertisedFeature(OFPortFeatures advertisedFeature) {
-            if (advertisedFeature == null) {
-                throw new
-                    NullPointerException("AdvertisedFeature must not be null");
-            }
-            this.advertisedFeatures.add(advertisedFeature);
-            return this;
-        }
-        /**
-         * @param supportedFeatures the supportedFeatures to set
-         */
-        public Builder addSupportedFeature(OFPortFeatures supportedFeature) {
-            if (supportedFeature == null) {
-                throw new NullPointerException("SupportedFeature must not be null");
-            }
-            this.supportedFeatures.add(supportedFeature);
-            return this;
-        }
-        /**
-         * @param peerFeatures the peerFeatures to set
-         */
-        public Builder addPeerFeature(OFPortFeatures peerFeature) {
-            if (peerFeature == null)
-                throw new NullPointerException("PortFeature must not be null");
-            this.peerFeatures.add(peerFeature);
-            return this;
-        }
-
-        /**
-         * @return
-         */
-        public ImmutablePort build() {
-            return new ImmutablePort(portNumber,
-                                     hardwareAddress,
-                                     name,
-                                     EnumSet.copyOf(config),
-                                     portStateLinkDown,
-                                     stpState,
-                                     EnumSet.copyOf(currentFeatures),
-                                     EnumSet.copyOf(advertisedFeatures),
-                                     EnumSet.copyOf(supportedFeatures),
-                                     EnumSet.copyOf(peerFeatures));
-        }
-    }
-
-
-    public static ImmutablePort fromOFPhysicalPort(OFPhysicalPort p) {
-        if (p == null) {
-            throw new NullPointerException("OFPhysicalPort must not be null");
-        }
-        if (p.getHardwareAddress() == null)  {
-            throw new NullPointerException("Hardware address must not be null");
-        }
-        if (p.getName() == null) {
-            throw new NullPointerException("Port name must not be null");
-        }
-
-        return new ImmutablePort(
-
-                p.getPortNumber(),
-                Arrays.copyOf(p.getHardwareAddress(), 6),
-                p.getName(),
-                EnumBitmaps.toEnumSet(OFPortConfig.class, p.getConfig()),
-                OFPortState.isPortDown(p.getState()),
-                OFPortState.getStpState(p.getState()),
-                EnumBitmaps.toEnumSet(OFPortFeatures.class,
-                                      p.getCurrentFeatures()),
-                EnumBitmaps.toEnumSet(OFPortFeatures.class,
-                                      p.getAdvertisedFeatures()),
-                EnumBitmaps.toEnumSet(OFPortFeatures.class,
-                                      p.getSupportedFeatures()),
-                EnumBitmaps.toEnumSet(OFPortFeatures.class,
-                                      p.getPeerFeatures())
-                                      );
-    }
-
-    public static ImmutablePort create(String name, Short portNumber) {
-        return new ImmutablePort(portNumber,
-                                         new byte[] { 0, 0, 0, 0, 0, 0 },
-                                         name,
-                                         EnumSet.noneOf(OFPortConfig.class),
-                                         false,
-                                         OFPortState.OFPPS_STP_LISTEN,
-                                         EnumSet.noneOf(OFPortFeatures.class),
-                                         EnumSet.noneOf(OFPortFeatures.class),
-                                         EnumSet.noneOf(OFPortFeatures.class),
-                                         EnumSet.noneOf(OFPortFeatures.class));
-    }
-
-    /**
-     * Private constructor. Use factory methods.
-     *
-     * Verifies pre-conditions of arguments
-     * Does NOT make defensive copies. Calling factory methods are required
-     * to copy defensively if required.
-     *
-     * @param portNumber
-     * @param hardwareAddress
-     * @param name
-     * @param config
-     * @param portStateLinkDown
-     * @param portStateStp
-     * @param currentFeatures
-     * @param advertisedFeatures
-     * @param supportedFeatures
-     * @param peerFeatures
-     */
-    private ImmutablePort(short portNumber, byte[] hardwareAddress,
-                                 String name, EnumSet<OFPortConfig> config,
-                                 boolean portStateLinkDown,
-                                 OFPortState portStateStp,
-                                 EnumSet<OFPortFeatures> currentFeatures,
-                                 EnumSet<OFPortFeatures> advertisedFeatures,
-                                 EnumSet<OFPortFeatures> supportedFeatures,
-                                 EnumSet<OFPortFeatures> peerFeatures) {
-        if (name == null) {
-            throw new NullPointerException("Port name must not be null");
-        }
-        if (hardwareAddress== null)  {
-            throw new NullPointerException("Hardware address must not be null");
-        }
-        if (hardwareAddress.length != 6) {
-            throw new IllegalArgumentException("Harware address must be 6 " +
-                    "bytes long but hardware address is " +
-                    Arrays.toString(hardwareAddress));
-        }
-        if (config == null)
-            throw new NullPointerException("portConfig must not be null");
-        if (portStateStp == null)
-            throw new NullPointerException("portStateStp must not be null");
-        if (currentFeatures == null)
-            throw new NullPointerException("currentFeatures must not be null");
-        if (advertisedFeatures == null)
-            throw new NullPointerException("advertisedFeatures must not be null");
-        if (supportedFeatures == null)
-            throw new NullPointerException("supportedFeatures must not be null");
-        if (peerFeatures == null)
-            throw new NullPointerException("peerFeatures must not be null");
-
-        this.portNumber = portNumber;
-        this.hardwareAddress = hardwareAddress;
-        this.name = name;
-        this.config = config;
-        this.portStateLinkDown = portStateLinkDown;
-        this.stpState = portStateStp;
-        this.currentFeatures = currentFeatures;
-        this.advertisedFeatures = advertisedFeatures;
-        this.supportedFeatures = supportedFeatures;
-        this.peerFeatures = peerFeatures;
-    }
-
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    public byte[] getHardwareAddress() {
-        // FIXME: don't use arrays.
-        return Arrays.copyOf(hardwareAddress, 6);
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public Set<OFPortConfig> getConfig() {
-        return Collections.unmodifiableSet(config);
-    }
-
-    /**
-     * Returns true if the OFPortState indicates the port is down
-     * @return
-     */
-    public boolean isLinkDown() {
-        return portStateLinkDown;
-    }
-
-    /**
-     * Returns the STP state portion of the OFPortState. The returned
-     * enum constant will be one of the four STP states and will have
-     * isStpState() return true
-     * @return
-     */
-    public OFPortState getStpState() {
-        return this.stpState;
-    }
-
-    public Set<OFPortFeatures> getCurrentFeatures() {
-        return Collections.unmodifiableSet(currentFeatures);
-    }
-
-    public Set<OFPortFeatures> getAdvertisedFeatures() {
-        return Collections.unmodifiableSet(advertisedFeatures);
-    }
-
-    public Set<OFPortFeatures> getSupportedFeatures() {
-        return Collections.unmodifiableSet(supportedFeatures);
-    }
-
-    public Set<OFPortFeatures> getPeerFeatures() {
-        return Collections.unmodifiableSet(peerFeatures);
-    }
-
-
-    /**
-     * Returns true if the port is up, i.e., it's neither administratively
-     * down nor link down. It currently does NOT take STP state into
-     * consideration
-     * @return
-     */
-    public boolean isEnabled() {
-        return (!portStateLinkDown &&
-                !config.contains(OFPortConfig.OFPPC_PORT_DOWN));
-    }
-
-    /**
-     * @return the speed of the port (from currentFeatures) if the port is
-     * enabled, otherwise return SPEED_NONE
-     */
-    public PortSpeed getCurrentPortSpeed() {
-        if (!isEnabled())
-            return PortSpeed.SPEED_NONE;
-        PortSpeed maxSpeed = PortSpeed.SPEED_NONE;
-        for (OFPortFeatures f: currentFeatures)
-            PortSpeed.max(maxSpeed, f.getSpeed());
-        return maxSpeed;
-    }
-
-    public OFPhysicalPort toOFPhysicalPort() {
-        OFPhysicalPort ofpp = new OFPhysicalPort();
-        ofpp.setPortNumber(this.getPortNumber());
-        ofpp.setHardwareAddress(this.getHardwareAddress());
-        ofpp.setName(this.getName());
-        ofpp.setConfig(EnumBitmaps.toBitmap(this.getConfig()));
-        int state = this.getStpState().getValue();
-        if (this.isLinkDown())
-            state |= OFPortState.OFPPS_LINK_DOWN.getValue();
-        ofpp.setState(state);
-        ofpp.setCurrentFeatures(EnumBitmaps.toBitmap(this.getCurrentFeatures()));
-        ofpp.setAdvertisedFeatures(
-                EnumBitmaps.toBitmap(this.getAdvertisedFeatures()));
-        ofpp.setSupportedFeatures(
-                EnumBitmaps.toBitmap(this.getSupportedFeatures()));
-        ofpp.setPeerFeatures(EnumBitmaps.toBitmap(this.getPeerFeatures()));
-        return ofpp;
-    }
-
-    /**
-     * Return a brief String describing this port containing the port number
-     * and port name
-     * @return
-     */
-    public String toBriefString() {
-        return String.format("%s (%d)", name, portNumber);
-    }
-
-
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime
-                 * result
-                 + ((advertisedFeatures == null) ? 0
-                                                : advertisedFeatures.hashCode());
-        result = prime * result + ((config == null) ? 0 : config.hashCode());
-        result = prime
-                 * result
-                 + ((currentFeatures == null) ? 0
-                                             : currentFeatures.hashCode());
-        result = prime * result + Arrays.hashCode(hardwareAddress);
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result
-                 + ((peerFeatures == null) ? 0 : peerFeatures.hashCode());
-        result = prime * result + portNumber;
-        result = prime * result + (portStateLinkDown ? 1231 : 1237);
-        result = prime * result
-                 + ((stpState == null) ? 0 : stpState.hashCode());
-        result = prime
-                 * result
-                 + ((supportedFeatures == null) ? 0
-                                               : supportedFeatures.hashCode());
-        return result;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) return true;
-        if (obj == null) return false;
-        if (getClass() != obj.getClass()) return false;
-        ImmutablePort other = (ImmutablePort) obj;
-        if (portNumber != other.portNumber) return false;
-        if (name == null) {
-            if (other.name != null) return false;
-        } else if (!name.equalsIgnoreCase(other.name)) return false;
-        if (advertisedFeatures == null) {
-            if (other.advertisedFeatures != null) return false;
-        } else if (!advertisedFeatures.equals(other.advertisedFeatures))
-            return false;
-        if (config == null) {
-            if (other.config != null) return false;
-        } else if (!config.equals(other.config)) return false;
-        if (currentFeatures == null) {
-            if (other.currentFeatures != null) return false;
-        } else if (!currentFeatures.equals(other.currentFeatures))
-            return false;
-        if (!Arrays.equals(hardwareAddress, other.hardwareAddress))
-            return false;
-        if (peerFeatures == null) {
-            if (other.peerFeatures != null) return false;
-        } else if (!peerFeatures.equals(other.peerFeatures)) return false;
-        if (portStateLinkDown != other.portStateLinkDown) return false;
-        if (stpState != other.stpState) return false;
-        if (supportedFeatures == null) {
-            if (other.supportedFeatures != null) return false;
-        } else if (!supportedFeatures.equals(other.supportedFeatures))
-            return false;
-        return true;
-    }
-
-    /**
-     * Convert a Collection of OFPhysicalPorts to a list of ImmutablePorts.
-     * All OFPhysicalPorts in the Collection must be non-null and valid.
-     * No other checks (name / number uniqueness) are performed
-     * @param ports
-     * @return a list of {@link ImmutablePort}s. This is list is owned by
-     * the caller. The returned list is not thread-safe
-     * @throws NullPointerException if any OFPhysicalPort or important fields
-     * of any OFPhysicalPort are null
-     * @throws IllegalArgumentException
-     */
-    public static List<ImmutablePort>
-            immutablePortListOf(Collection<OFPhysicalPort> ports) {
-        if (ports == null) {
-            throw new NullPointerException("Port list must not be null");
-        }
-        ArrayList<ImmutablePort> immutablePorts =
-                new ArrayList<ImmutablePort>(ports.size());
-        for (OFPhysicalPort p: ports)
-            immutablePorts.add(fromOFPhysicalPort(p));
-        return immutablePorts;
-    }
-
-    /**
-     * Convert a Collection of ImmutablePort to a list of OFPhyscialPorts.
-     * All ImmutablePorts in the Collection must be non-null.
-     * No other checks (name / number uniqueness) are performed
-     * @param ports
-     * @return a list of {@link OFPhysicalPort}s. This is list is owned by
-     * the caller. The returned list is not thread-safe
-     * @throws NullPointerException if any {@link ImmutablePort} or the port
-     * list is null
-     * @throws IllegalArgumentException
-     */
-    public static List<OFPhysicalPort>
-            ofPhysicalPortListOf(Collection<ImmutablePort> ports) {
-        if (ports == null) {
-            throw new NullPointerException("Port list must not be null");
-        }
-        ArrayList<OFPhysicalPort> ofppList=
-                new ArrayList<OFPhysicalPort>(ports.size());
-        for (ImmutablePort p: ports) {
-            if (p == null)
-                throw new NullPointerException("Port must not be null");
-            ofppList.add(p.toOFPhysicalPort());
-        }
-        return ofppList;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        StringBuilder builder2 = new StringBuilder();
-        String linkState = (portStateLinkDown) ? "DOWN" : "UP";
-        builder2.append("Port [")
-                .append(name)
-                .append("(").append(portNumber).append(")")
-                .append(", hardwareAddress=")
-                .append(HexString.toHexString(hardwareAddress))
-                .append(", config=").append(config)
-                .append(", link=").append(linkState)
-                .append(", stpState=").append(stpState)
-                .append(", currentFeatures=").append(currentFeatures)
-                .append(", advertisedFeatures=").append(advertisedFeatures)
-                .append(", supportedFeatures=").append(supportedFeatures)
-                .append(", peerFeatures=").append(peerFeatures).append("]");
-        return builder2.toString();
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/LogicalOFMessageCategory.java b/src/main/java/net/floodlightcontroller/core/LogicalOFMessageCategory.java
new file mode 100644
index 000000000..514d3541c
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/LogicalOFMessageCategory.java
@@ -0,0 +1,68 @@
+package net.floodlightcontroller.core;
+
+import javax.annotation.Nonnull;
+
+import org.projectfloodlight.openflow.types.OFAuxId;
+
+/**
+ * Immutable class for logical OF message category.
+ * Applications should use these to define the OF Aux connections
+ * that they desire.
+ * @author Jason Parraga <Jason.Parraga@bigswitch.com>
+ */
+public class LogicalOFMessageCategory {
+
+    public static final LogicalOFMessageCategory MAIN =  new LogicalOFMessageCategory("MAIN", OFAuxId.MAIN);
+
+    final private String name;
+    final private OFAuxId auxId;
+
+
+    public LogicalOFMessageCategory(@Nonnull String name, int auxId) {
+        this(name, OFAuxId.of(auxId));
+    }
+
+    public LogicalOFMessageCategory(@Nonnull String name, OFAuxId auxId) {
+        if (name == null)
+            throw new NullPointerException("name must not be null");
+        this.name = name;
+        this.auxId = auxId;
+    }
+
+    public OFAuxId getAuxId(){
+        return this.auxId;
+    }
+
+    public String getName(){
+        return this.name;
+    }
+
+    @Override
+    public String toString(){
+        return "LogicalOFMessageCategory [name=" + getName() + " OFAuxId=" + getAuxId() + "]";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((auxId == null) ? 0 : auxId.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        LogicalOFMessageCategory other = (LogicalOFMessageCategory) obj;
+        if (auxId == null) {
+            if (other.auxId != null) return false;
+        } else if (!auxId.equals(other.auxId)) return false;
+        if (name == null) {
+            if (other.name != null) return false;
+        } else if (!name.equals(other.name)) return false;
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/Main.java b/src/main/java/net/floodlightcontroller/core/Main.java
index 627a56c14..f57ed991a 100644
--- a/src/main/java/net/floodlightcontroller/core/Main.java
+++ b/src/main/java/net/floodlightcontroller/core/Main.java
@@ -18,48 +18,68 @@ package net.floodlightcontroller.core;
 
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.CmdLineParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import net.floodlightcontroller.core.internal.CmdLineSettings;
+import net.floodlightcontroller.core.module.FloodlightModuleConfigFileNotFoundException;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.FloodlightModuleLoader;
 import net.floodlightcontroller.core.module.IFloodlightModuleContext;
-import net.floodlightcontroller.restserver.IRestApiService;
 
 /**
  * Host for the Floodlight main method
  * @author alexreimers
  */
 public class Main {
+	private static final Logger logger = LoggerFactory.getLogger(Main.class);
 
-    /**
-     * Main method to load configuration and modules
-     * @param args
-     * @throws FloodlightModuleException 
-     */
-    public static void main(String[] args) throws FloodlightModuleException {
-        // Setup logger
-        System.setProperty("org.restlet.engine.loggerFacadeClass", 
-                "org.restlet.ext.slf4j.Slf4jLoggerFacade");
-        
-        CmdLineSettings settings = new CmdLineSettings();
-        CmdLineParser parser = new CmdLineParser(settings);
-        try {
-            parser.parseArgument(args);
-        } catch (CmdLineException e) {
-            parser.printUsage(System.out);
-            System.exit(1);
-        }
-        
-        // Load modules
-        FloodlightModuleLoader fml = new FloodlightModuleLoader();
-        IFloodlightModuleContext moduleContext = fml.loadModulesFromConfig(settings.getModuleFile());
-        // Run REST server
-        IRestApiService restApi = moduleContext.getServiceImpl(IRestApiService.class);
-        restApi.run();
-        // Run the main floodlight module
-        IFloodlightProviderService controller =
-                moduleContext.getServiceImpl(IFloodlightProviderService.class);
-        // This call blocks, it has to be the last line in the main
-        controller.run();
-    }
+	/**
+	 * Main method to load configuration and modules
+	 * @param args
+	 * @throws FloodlightModuleException 
+	 */
+	public static void main(String[] args) throws FloodlightModuleException {
+		try {
+			// Setup logger
+			System.setProperty("org.restlet.engine.loggerFacadeClass", 
+					"org.restlet.ext.slf4j.Slf4jLoggerFacade");
+
+			CmdLineSettings settings = new CmdLineSettings();
+			CmdLineParser parser = new CmdLineParser(settings);
+			try {
+				parser.parseArgument(args);
+			} catch (CmdLineException e) {
+				parser.printUsage(System.out);
+				System.exit(1);
+			}
+
+			// Load modules
+			FloodlightModuleLoader fml = new FloodlightModuleLoader();
+			try {
+				IFloodlightModuleContext moduleContext = fml.loadModulesFromConfig(settings.getModuleFile());
+				//TODO @Ryan I don't think we need this anymore... Run REST server
+				//IRestApiService restApi = moduleContext.getServiceImpl(IRestApiService.class);
+				//restApi.run();
+				// Run the main floodlight module
+				//IFloodlightProviderService controller =
+				//        moduleContext.getServiceImpl(IFloodlightProviderService.class);
+				// This call blocks, it has to be the last line in the main
+				//controller.run();
+			} catch (FloodlightModuleConfigFileNotFoundException e) {
+				// we really want to log the message, not the stack trace
+				logger.error("Could not read config file: {}", e.getMessage());
+				System.exit(1);
+			}
+			try {
+                fml.runModules(); // this should run the controller module and all modules
+            } catch (FloodlightModuleException e) {
+                logger.error("Failed to run controller modules", e);
+                System.exit(1);
+            }
+		} catch (Exception e) {
+			logger.error("Exception in main", e);
+			System.exit(1);
+		}
+	}
 }
diff --git a/src/main/java/net/floodlightcontroller/core/OFConnection.java b/src/main/java/net/floodlightcontroller/core/OFConnection.java
new file mode 100644
index 000000000..ff4f529bf
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/OFConnection.java
@@ -0,0 +1,409 @@
+/**
+ *    Copyright 2012, Big Switch Networks, Inc.
+ *    Originally created by David Erickson, Stanford University
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+
+package net.floodlightcontroller.core;
+
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.annotation.Nonnull;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.Timer;
+import org.jboss.netty.util.TimerTask;
+
+import java.util.Date;
+
+import net.floodlightcontroller.core.annotations.LogMessageDoc;
+import net.floodlightcontroller.core.internal.Controller;
+import net.floodlightcontroller.core.internal.IOFConnectionListener;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFRequest;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFAuxId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Implementation of an openflow connection to switch. Encapsulates a
+ * {@link Channel}, and provides message write and request/response handling
+ * capabilities.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class OFConnection implements IOFConnection, IOFConnectionBackend{
+    private static final Logger logger = LoggerFactory.getLogger(OFConnection.class);
+    private final DatapathId dpid;
+    private final OFFactory factory;
+    private final Channel channel;
+    private final OFAuxId auxId;
+    private final Timer timer;
+
+    private final Date connectedSince;
+
+    private final Map<Long, Deliverable<?>> xidDeliverableMap;
+
+    protected final static ThreadLocal<List<OFMessage>> localMsgBuffer =
+            new ThreadLocal<List<OFMessage>>();
+
+    private static final long DELIVERABLE_TIME_OUT = 60;
+    private static final TimeUnit DELIVERABLE_TIME_OUT_UNIT = TimeUnit.SECONDS;
+
+
+    private final OFConnectionCounters counters;
+    private IOFConnectionListener listener;
+
+    public OFConnection(@Nonnull DatapathId dpid,
+                        @Nonnull OFFactory factory,
+                        @Nonnull Channel channel,
+                        @Nonnull OFAuxId auxId,
+                        @Nonnull IDebugCounterService debugCounters,
+                        @Nonnull Timer timer) {
+        Preconditions.checkNotNull(dpid, "dpid");
+        Preconditions.checkNotNull(factory, "factory");
+        Preconditions.checkNotNull(channel, "channel");
+        Preconditions.checkNotNull(timer, "timer");
+        Preconditions.checkNotNull(debugCounters);
+
+        this.listener = NullConnectionListener.INSTANCE;
+        this.dpid = dpid;
+        this.factory = factory;
+        this.channel = channel;
+        this.auxId = auxId;
+        this.connectedSince = new Date();
+        this.xidDeliverableMap = new ConcurrentHashMap<>();
+        this.counters = new OFConnectionCounters(debugCounters, dpid, this.auxId);
+        this.timer = timer;
+    }
+
+    @Override
+    public void write(OFMessage m) {
+        if (!isConnected()) {
+            if (logger.isDebugEnabled())
+                logger.debug("{}: not connected - dropping message {}", this, m);
+            return;
+        }
+        if (logger.isTraceEnabled())
+            logger.trace("{}: send {}", this, m);
+        List<OFMessage> msgBuffer = localMsgBuffer.get();
+        if (msgBuffer == null) {
+            msgBuffer = new ArrayList<OFMessage>();
+            localMsgBuffer.set(msgBuffer);
+        }
+
+        counters.updateWriteStats(m);
+        msgBuffer.add(m);
+
+        if ((msgBuffer.size() >= Controller.BATCH_MAX_SIZE)
+                || ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) {
+            this.write(msgBuffer);
+            localMsgBuffer.set(null);
+        }
+    }
+
+    @Override
+    public <R extends OFMessage> ListenableFuture<R> writeRequest(OFRequest<R> request) {
+        if (!isConnected())
+            return Futures.immediateFailedFuture(new SwitchDisconnectedException(getDatapathId()));
+
+        DeliverableListenableFuture<R> future = new DeliverableListenableFuture<R>();
+        xidDeliverableMap.put(request.getXid(), future);
+        write(request);
+        return future;
+    }
+
+    @Override
+    @LogMessageDoc(level = "WARN",
+                   message = "Sending OF message that modifies switch "
+                           + "state while in the slave role: {switch}",
+                   explanation = "An application has sent a message to a switch "
+                           + "that is not valid when the switch is in a slave role",
+                   recommendation = LogMessageDoc.REPORT_CONTROLLER_BUG)
+    public void write(Iterable<OFMessage> msglist) {
+        if (!isConnected()) {
+            if (logger.isDebugEnabled())
+                logger.debug(this.toString() + " : not connected - dropping {} element msglist {} ",
+                        Iterables.size(msglist),
+                        String.valueOf(msglist).substring(0, 80));
+            return;
+        }
+        for (OFMessage m : msglist) {
+            if (logger.isTraceEnabled())
+                logger.trace("{}: send {}", this, m);
+            counters.updateWriteStats(m);
+        }
+        this.channel.write(msglist);
+    }
+
+    // Notifies the connection object that the channel has been disconnected
+    public void disconnected() {
+        SwitchDisconnectedException exception = new SwitchDisconnectedException(getDatapathId());
+        for (Long xid : xidDeliverableMap.keySet()) {
+            // protect against other mechanisms running at the same time
+            // (timeout)
+            Deliverable<?> removed = xidDeliverableMap.remove(xid);
+            if (removed != null) {
+                removed.deliverError(exception);
+            }
+        }
+    }
+
+    @Override
+    public void disconnect() {
+        this.channel.disconnect();
+    }
+
+    @Override
+    public String toString() {
+        String channelString = (channel != null) ? String.valueOf(channel.getRemoteAddress()): "?";
+        return "OFConnection [" + getDatapathId() + "(" + getAuxId() + ")" + "@" + channelString + "]";
+    }
+
+    @Override
+    public Date getConnectedSince() {
+        return connectedSince;
+    }
+
+    @Override
+    public <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest(
+            OFStatsRequest<REPLY> request) {
+        if (!isConnected())
+            return Futures.immediateFailedFuture(new SwitchDisconnectedException(getDatapathId()));
+
+        final DeliverableListenableFuture<List<REPLY>> future =
+                new DeliverableListenableFuture<List<REPLY>>();
+
+        Deliverable<REPLY> deliverable = new Deliverable<REPLY>() {
+            private final List<REPLY> results = Collections
+                    .synchronizedList(new ArrayList<REPLY>());
+
+            @Override
+            public void deliver(REPLY reply) {
+                results.add(reply);
+                if (!reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
+                    // done
+                    future.deliver(results);
+                }
+            }
+
+            @Override
+            public void deliverError(Throwable cause) {
+                future.deliverError(cause);
+            }
+
+            @Override
+            public boolean isDone() {
+                return future.isDone();
+            }
+
+            @Override
+            public boolean cancel(boolean mayInterruptIfRunning) {
+                return future.cancel(mayInterruptIfRunning);
+            }
+        };
+
+        registerDeliverable(request.getXid(), deliverable);
+        this.write(request);
+        return future;
+    }
+
+    private void registerDeliverable(long xid, Deliverable<?> deliverable) {
+        this.xidDeliverableMap.put(xid, deliverable);
+        timer.newTimeout(new TimeOutDeliverable(xid), DELIVERABLE_TIME_OUT, DELIVERABLE_TIME_OUT_UNIT);
+    }
+
+    public boolean handleGenericDeliverable(OFMessage reply) {
+        counters.updateReadStats(reply);
+        @SuppressWarnings("unchecked")
+        Deliverable<OFMessage> deliverable =
+                (Deliverable<OFMessage>) this.xidDeliverableMap.get(reply.getXid());
+        if (deliverable != null) {
+            if(reply instanceof OFErrorMsg) {
+                deliverable.deliverError(new OFErrorMsgException((OFErrorMsg) reply));
+            } else {
+                deliverable.deliver(reply);
+            }
+            if (deliverable.isDone())
+                this.xidDeliverableMap.remove(reply.getXid());
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public void cancelAllPendingRequests() {
+        /*
+         * we don't need to be synchronized here. Even if another thread
+         * modifies the map while we're cleaning up the future will eventually
+         * timeout
+         */
+        for (Deliverable<?> d : xidDeliverableMap.values()) {
+            d.cancel(true);
+        }
+        xidDeliverableMap.clear();
+    }
+
+    @Override
+    public boolean isConnected() {
+        return channel.isConnected();
+    }
+
+    @Override
+    public void flush() {
+        List<OFMessage> msglist = localMsgBuffer.get();
+        if ((msglist != null) && (msglist.size() > 0)) {
+            this.write(msglist);
+            localMsgBuffer.set(null);
+        }
+    }
+
+    @Override
+    public SocketAddress getRemoteInetAddress() {
+        return channel.getRemoteAddress();
+    }
+
+    @Override
+    public SocketAddress getLocalInetAddress() {
+        return channel.getLocalAddress();
+    }
+
+    public boolean deliverResponse(OFMessage m) {
+        if (handleGenericDeliverable(m))
+            return true;
+        else
+            return false;
+    }
+
+    @Override
+    public boolean isWritable() {
+        return channel.isWritable();
+    }
+
+    @Override
+    public DatapathId getDatapathId() {
+        return dpid;
+    }
+
+    @Override
+    public OFAuxId getAuxId() {
+        return auxId;
+    }
+
+    Set<Long> getPendingRequestIds() {
+        return ImmutableSet.copyOf(xidDeliverableMap.keySet());
+    }
+
+    @Override
+    public OFFactory getOFFactory() {
+        return this.factory;
+    }
+
+    /**
+     * Timeout class instantiated for deliverables. Will throw a timeout exception
+     * if proper responses are not received in time.
+     *
+     */
+    private class TimeOutDeliverable implements TimerTask {
+        private final long xid;
+
+        public TimeOutDeliverable(long xid) {
+            this.xid = xid;
+        }
+
+        @Override
+        public void run(Timeout timeout) throws Exception {
+            Deliverable<?> removed = xidDeliverableMap.remove(xid);
+            if (removed != null && !removed.isDone()) {
+                removed.deliverError(new TimeoutException(
+                        "timeout - did not receive answer for xid " + xid));
+            }
+
+        }
+    }
+
+    public IOFConnectionListener getListener() {
+        return listener;
+    }
+
+    /** set the connection listener
+     *  <p>
+     *  Note: this is assumed to be called from the Connection's IO Thread.
+     *
+     * @param listener
+     */
+    @Override
+    public void setListener(IOFConnectionListener listener) {
+        this.listener = listener;
+    }
+
+    public void messageReceived(OFMessage m) {
+        // Check if message was a response for a xid waiting at the switch
+        if(!deliverResponse(m)){
+            listener.messageReceived(this, m);
+        }
+    }
+
+    /** A dummy connection listener that just logs warn messages. Saves us a few null checks
+     * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+     */
+    private static class NullConnectionListener implements IOFConnectionListener {
+        public final static NullConnectionListener INSTANCE = new NullConnectionListener();
+
+        private NullConnectionListener() { }
+
+        @Override
+        public void connectionClosed(IOFConnectionBackend connection) {
+            logger.warn("NullConnectionListener for {} - received connectionClosed", connection);
+        }
+
+        @Override
+        public void messageReceived(IOFConnectionBackend connection, OFMessage m) {
+            logger.warn("NullConnectionListener for {} - received messageReceived: {}", connection, m);
+        }
+
+        @Override
+        public boolean isSwitchHandshakeComplete(IOFConnectionBackend connection) {
+            return false;
+        }
+
+    }
+
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java b/src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java
new file mode 100644
index 000000000..403fb4bbd
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/OFConnectionCounters.java
@@ -0,0 +1,710 @@
+package net.floodlightcontroller.core;
+
+import net.floodlightcontroller.debugcounter.IDebugCounter;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFAuxId;
+import org.python.google.common.base.Preconditions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of Counters for per-connection statistics for OpenFlow
+ * messages.
+ * @author Alok Shankar <alok@bigswitch.com>
+ */
+public class OFConnectionCounters {
+    public static final String COUNTER_MODULE = OFConnectionCounters.class.getPackage().getName();
+
+    /**
+     * Counters for open flow message types
+     */
+    // Write Counters
+    //
+    private final IDebugCounter ctrWriteHello;
+    private final IDebugCounter ctrWriteError;
+    private final IDebugCounter ctrWriteEchoRequest;
+    private final IDebugCounter ctrWriteEchoReply;
+    private final IDebugCounter ctrWriteExperimenter;
+    private final IDebugCounter ctrWriteFeaturesRequest;
+    private final IDebugCounter ctrWriteFeaturesReply;
+    private final IDebugCounter ctrWriteGetConfigRequest;
+    private final IDebugCounter ctrWriteGetConfigReply;
+    private final IDebugCounter ctrWriteSetConfig;
+    private final IDebugCounter ctrWritePacketIn;
+    private final IDebugCounter ctrWritePacketOut;
+    private final IDebugCounter ctrWriteFlowRemoved;
+    private final IDebugCounter ctrWritePortStatus;
+    private final IDebugCounter ctrWriteFlowMod;
+    private final IDebugCounter ctrWritePortMod;
+    private final IDebugCounter ctrWriteStatsRequest;
+    private final IDebugCounter ctrWriteStatsReply;
+    private final IDebugCounter ctrWriteBarrierRequest;
+    private final IDebugCounter ctrWriteBarrierReply;
+    private final IDebugCounter ctrWriteGetAsyncReply;
+    private final IDebugCounter ctrWriteGetAsyncRequest;
+    private final IDebugCounter ctrWriteGroupMod;
+    private final IDebugCounter ctrWriteMeterMod;
+    private final IDebugCounter ctrWriteQueueGetConfigReply;
+    private final IDebugCounter ctrWriteQueueGetConfigRequest;
+    private final IDebugCounter ctrWriteRoleRequest;
+    private final IDebugCounter ctrWriteRoleReply;
+    private final IDebugCounter ctrWriteSetAsync;
+    private final IDebugCounter ctrWriteTableMod;
+
+    // Read Counters
+    //
+    private final IDebugCounter ctrReadHello;
+    private final IDebugCounter ctrReadError;
+    private final IDebugCounter ctrReadEchoRequest;
+    private final IDebugCounter ctrReadEchoReply;
+    private final IDebugCounter ctrReadExperimenter;
+    private final IDebugCounter ctrReadFeaturesRequest;
+    private final IDebugCounter ctrReadFeaturesReply;
+    private final IDebugCounter ctrReadGetConfigRequest;
+    private final IDebugCounter ctrReadGetConfigReply;
+    private final IDebugCounter ctrReadSetConfig;
+    private final IDebugCounter ctrReadPacketIn;
+    private final IDebugCounter ctrReadPacketOut;
+    private final IDebugCounter ctrReadFlowRemoved;
+    private final IDebugCounter ctrReadPortStatus;
+    private final IDebugCounter ctrReadFlowMod;
+    private final IDebugCounter ctrReadPortMod;
+    private final IDebugCounter ctrReadStatsRequest;
+    private final IDebugCounter ctrReadStatsReply;
+    private final IDebugCounter ctrReadBarrierRequest;
+    private final IDebugCounter ctrReadBarrierReply;
+    private final IDebugCounter ctrReadGetAsyncReply;
+    private final IDebugCounter ctrReadGetAsyncRequest;
+    private final IDebugCounter ctrReadGroupMod;
+    private final IDebugCounter ctrReadMeterMod;
+    private final IDebugCounter ctrReadQueueGetConfigReply;
+    private final IDebugCounter ctrReadQueueGetConfigRequest;
+    private final IDebugCounter ctrReadRoleRequest;
+    private final IDebugCounter ctrReadRoleReply;
+    private final IDebugCounter ctrReadSetAsync;
+    private final IDebugCounter ctrReadTableMod;
+
+    private static final Logger logger =
+            LoggerFactory.getLogger(OFConnectionCounters.class);
+
+    /**
+     * Utility function to create description string and do counter registration
+     * @param countersService
+     * @param stringId The string ID
+     * @param messageType Type of open flow message
+     * @return the registered DebugCounter
+     */
+    IDebugCounter registerCounterLocal(IDebugCounterService countersService,
+                                       String hierarchy,
+                                       String stringId,
+                                       String messageType){
+        String counterHierarchy = stringId + hierarchy + "/" + messageType;
+        String counterDescription = "Number of " + messageType +
+                                        " messages in this connection";
+
+        return countersService.registerCounter(COUNTER_MODULE, counterHierarchy,
+                                               counterDescription);
+    }
+
+    public OFConnectionCounters(IDebugCounterService counters,
+                                DatapathId dpid,
+                                OFAuxId auxId) {
+
+        Preconditions.checkNotNull(counters, "Counters must not be null");
+        Preconditions.checkNotNull(dpid, "dpid must not be null");
+        Preconditions.checkNotNull(auxId, "auxid must not be null");
+
+        String stringId = dpid.toString() +":" + auxId.toString();
+        String hierarchy = "/write";
+
+        // every level of the hierarchical counter has to be registered
+        // even if they are not used
+
+        counters.registerCounter(COUNTER_MODULE, stringId ,
+                                 "Counter for this connection");
+
+        registerCounterLocal(counters,
+                             hierarchy,
+                             stringId,
+                             "");
+
+        ctrWriteHello =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.HELLO.toString());
+        ctrWriteError =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ERROR.toString());
+        ctrWriteEchoRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ECHO_REQUEST.toString());
+        ctrWriteEchoReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ECHO_REPLY.toString());
+        ctrWriteExperimenter =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.EXPERIMENTER.toString());
+        ctrWriteFeaturesRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.FEATURES_REQUEST.toString());
+        ctrWriteFeaturesReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.FEATURES_REPLY.toString());
+        ctrWriteGetConfigRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GET_CONFIG_REQUEST.toString());
+        ctrWriteGetConfigReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GET_CONFIG_REPLY.toString());
+        ctrWriteSetConfig =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.SET_CONFIG.toString());
+        ctrWritePacketIn =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.PACKET_IN.toString());
+        ctrWritePacketOut =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.PACKET_OUT.toString());
+        ctrWriteFlowRemoved =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.FLOW_REMOVED.toString());
+        ctrWritePortStatus =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.PORT_STATUS.toString());
+        ctrWriteFlowMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.FLOW_MOD.toString());
+        ctrWritePortMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.PORT_MOD.toString());
+        ctrWriteStatsRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.STATS_REQUEST.toString());
+        ctrWriteStatsReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.STATS_REPLY.toString());
+        ctrWriteBarrierRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.BARRIER_REQUEST.toString());
+        ctrWriteBarrierReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.BARRIER_REPLY.toString());
+        ctrWriteGetAsyncReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GET_ASYNC_REPLY.toString());
+        ctrWriteGetAsyncRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GET_ASYNC_REQUEST.toString());
+        ctrWriteGroupMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GROUP_MOD.toString());
+        ctrWriteMeterMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.METER_MOD.toString());
+        ctrWriteQueueGetConfigReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.QUEUE_GET_CONFIG_REPLY.toString());
+        ctrWriteQueueGetConfigRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.QUEUE_GET_CONFIG_REQUEST.toString());
+        ctrWriteRoleReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ROLE_REPLY.toString());
+        ctrWriteRoleRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ROLE_REQUEST.toString());
+        ctrWriteSetAsync =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.SET_ASYNC.toString());
+        ctrWriteTableMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.TABLE_MOD.toString());
+
+        // Register Read Counters
+        //
+        hierarchy = "/read";
+
+        registerCounterLocal(counters,
+                             hierarchy,
+                             stringId,
+                             "");
+        ctrReadHello =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.HELLO.toString());
+        ctrReadError =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ERROR.toString());
+        ctrReadEchoRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ECHO_REQUEST.toString());
+        ctrReadEchoReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ECHO_REPLY.toString());
+        ctrReadExperimenter =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.EXPERIMENTER.toString());
+        ctrReadFeaturesRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.FEATURES_REQUEST.toString());
+        ctrReadFeaturesReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.FEATURES_REPLY.toString());
+        ctrReadGetConfigRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GET_CONFIG_REQUEST.toString());
+        ctrReadGetConfigReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GET_CONFIG_REPLY.toString());
+        ctrReadSetConfig =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.SET_CONFIG.toString());
+        ctrReadPacketIn =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.PACKET_IN.toString());
+        ctrReadPacketOut =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.PACKET_OUT.toString());
+        ctrReadFlowRemoved =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.FLOW_REMOVED.toString());
+        ctrReadPortStatus =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.PORT_STATUS.toString());
+        ctrReadFlowMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.FLOW_MOD.toString());
+        ctrReadPortMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.PORT_MOD.toString());
+        ctrReadStatsRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.STATS_REQUEST.toString());
+        ctrReadStatsReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.STATS_REPLY.toString());
+        ctrReadBarrierRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.BARRIER_REQUEST.toString());
+        ctrReadBarrierReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.BARRIER_REPLY.toString());
+        ctrReadGetAsyncReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GET_ASYNC_REPLY.toString());
+        ctrReadGetAsyncRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GET_ASYNC_REQUEST.toString());
+        ctrReadGroupMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.GROUP_MOD.toString());
+        ctrReadMeterMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.METER_MOD.toString());
+        ctrReadQueueGetConfigReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.QUEUE_GET_CONFIG_REPLY.toString());
+        ctrReadQueueGetConfigRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.QUEUE_GET_CONFIG_REQUEST.toString());
+        ctrReadRoleReply =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ROLE_REPLY.toString());
+        ctrReadRoleRequest =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.ROLE_REQUEST.toString());
+        ctrReadSetAsync =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.SET_ASYNC.toString());
+        ctrReadTableMod =
+                registerCounterLocal(counters,
+                                     hierarchy,
+                                     stringId,
+                                     OFType.TABLE_MOD.toString());
+    }
+
+   /**
+    * Update Write Counters for Open flow messages
+    * @param ofm openflow message
+    */
+   public void updateWriteStats(OFMessage ofm) {
+         switch(ofm.getType()){
+            case BARRIER_REPLY:
+                ctrWriteBarrierReply.increment();
+                break;
+
+            case BARRIER_REQUEST:
+                ctrWriteBarrierRequest.increment();
+                break;
+
+            case ECHO_REPLY:
+                ctrWriteEchoReply.increment();
+                break;
+
+            case ECHO_REQUEST:
+                ctrWriteEchoRequest.increment();
+                break;
+
+            case ERROR:
+                ctrWriteError.increment();
+                break;
+
+            case EXPERIMENTER:
+                ctrWriteExperimenter.increment();
+                break;
+
+            case FEATURES_REPLY:
+                ctrWriteFeaturesReply.increment();
+                break;
+
+            case FEATURES_REQUEST:
+                ctrWriteFeaturesRequest.increment();
+                break;
+
+            case FLOW_MOD:
+                ctrWriteFlowMod.increment();
+                break;
+
+            case FLOW_REMOVED:
+                ctrWriteFlowRemoved.increment();
+                break;
+
+            case GET_ASYNC_REPLY:
+                ctrWriteGetAsyncReply.increment();
+                break;
+
+            case GET_ASYNC_REQUEST:
+                ctrWriteGetAsyncRequest.increment();
+                break;
+
+            case GET_CONFIG_REPLY:
+                ctrWriteGetConfigReply.increment();
+                break;
+
+            case GET_CONFIG_REQUEST:
+                ctrWriteGetConfigRequest.increment();
+                break;
+
+            case GROUP_MOD:
+                ctrWriteGroupMod.increment();
+                break;
+
+            case HELLO:
+                ctrWriteHello.increment();
+                break;
+
+            case METER_MOD:
+                ctrWriteMeterMod.increment();
+                break;
+
+            case PACKET_IN:
+                ctrWritePacketIn.increment();
+                break;
+
+            case PACKET_OUT:
+                ctrWritePacketOut.increment();
+                break;
+
+            case PORT_MOD:
+                ctrWritePortMod.increment();
+                break;
+
+            case PORT_STATUS:
+                ctrWritePortStatus.increment();
+                break;
+
+            case QUEUE_GET_CONFIG_REPLY:
+                ctrWriteQueueGetConfigReply.increment();
+                break;
+
+            case QUEUE_GET_CONFIG_REQUEST:
+                ctrWriteQueueGetConfigRequest.increment();
+                break;
+
+            case ROLE_REPLY:
+                ctrWriteRoleReply.increment();
+                break;
+
+            case ROLE_REQUEST:
+                ctrWriteRoleRequest.increment();
+                break;
+
+            case SET_ASYNC:
+                ctrWriteSetAsync.increment();
+                break;
+
+            case SET_CONFIG:
+                ctrWriteSetConfig.increment();
+                break;
+
+            case STATS_REPLY:
+                ctrWriteStatsReply.increment();
+                break;
+
+            case STATS_REQUEST:
+                ctrWriteStatsRequest.increment();
+                break;
+
+            case TABLE_MOD:
+                ctrWriteTableMod.increment();
+                break;
+
+            default:
+                logger.warn(ofm.getType().toString() +
+                            ": Invalid OpenFlow Messaqe!");
+                break;
+         }
+    }
+
+   /**
+    * Update Read openflow counters for this connection
+    * @param ofm Open Flow Message
+    */
+   public void updateReadStats(OFMessage ofm){
+       switch(ofm.getType()){
+           case BARRIER_REPLY:
+               ctrReadBarrierReply.increment();
+               break;
+
+           case BARRIER_REQUEST:
+               ctrReadBarrierRequest.increment();
+               break;
+
+           case ECHO_REPLY:
+               ctrReadEchoReply.increment();
+               break;
+
+           case ECHO_REQUEST:
+               ctrReadEchoRequest.increment();
+               break;
+
+           case ERROR:
+               ctrReadError.increment();
+               break;
+
+           case EXPERIMENTER:
+               ctrReadExperimenter.increment();
+               break;
+
+           case FEATURES_REPLY:
+               ctrReadFeaturesReply.increment();
+               break;
+
+           case FEATURES_REQUEST:
+               ctrReadFeaturesRequest.increment();
+               break;
+
+           case FLOW_MOD:
+               ctrReadFlowMod.increment();
+               break;
+
+           case FLOW_REMOVED:
+               ctrReadFlowRemoved.increment();
+               break;
+
+           case GET_ASYNC_REPLY:
+               ctrReadGetAsyncReply.increment();
+               break;
+
+           case GET_ASYNC_REQUEST:
+               ctrReadGetAsyncRequest.increment();
+               break;
+
+           case GET_CONFIG_REPLY:
+               ctrReadGetConfigReply.increment();
+               break;
+
+           case GET_CONFIG_REQUEST:
+               ctrReadGetConfigRequest.increment();
+               break;
+
+           case GROUP_MOD:
+               ctrReadGroupMod.increment();
+               break;
+
+           case HELLO:
+               ctrReadHello.increment();
+               break;
+
+           case METER_MOD:
+               ctrReadMeterMod.increment();
+               break;
+
+           case PACKET_IN:
+               ctrReadPacketIn.increment();
+               break;
+
+           case PACKET_OUT:
+               ctrReadPacketOut.increment();
+               break;
+
+           case PORT_MOD:
+               ctrReadPortMod.increment();
+               break;
+
+           case PORT_STATUS:
+               ctrReadPortStatus.increment();
+               break;
+
+           case QUEUE_GET_CONFIG_REPLY:
+               ctrReadQueueGetConfigReply.increment();
+               break;
+
+           case QUEUE_GET_CONFIG_REQUEST:
+               ctrReadQueueGetConfigRequest.increment();
+               break;
+
+           case ROLE_REPLY:
+               ctrReadRoleReply.increment();
+               break;
+
+           case ROLE_REQUEST:
+               ctrReadRoleRequest.increment();
+               break;
+
+           case SET_ASYNC:
+               ctrReadSetAsync.increment();
+               break;
+
+           case SET_CONFIG:
+               ctrReadSetConfig.increment();
+               break;
+
+           case STATS_REPLY:
+               ctrReadStatsReply.increment();
+               break;
+
+           case STATS_REQUEST:
+               ctrReadStatsRequest.increment();
+               break;
+
+           case TABLE_MOD:
+               ctrReadTableMod.increment();
+               break;
+
+           default:
+               logger.warn(ofm.getType().toString() +
+                           ": Invalid OpenFlow Messaqe!");
+               break;
+        }
+   }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java b/src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java
new file mode 100644
index 000000000..f990f0a45
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/OFErrorMsgException.java
@@ -0,0 +1,28 @@
+package net.floodlightcontroller.core;
+
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFRequest;
+
+/** raised/reported by Futures in @IOFConnection when a an
+ *  {@link OFErrorMsg} is received in response to a {@link OFRequest}
+ *  sent via {@link OFConnection#writeRequest(OFRequest)} or
+ *  {@link OFConnection#writeStatsRequest(org.projectfloodlight.openflow.protocol.OFStatsRequest)}.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class OFErrorMsgException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    private final OFErrorMsg errorMessage;
+
+    public OFErrorMsgException(final OFErrorMsg errorMessage) {
+        super("OF error received: " + errorMessage.toString());
+        this.errorMessage = errorMessage;
+    }
+
+    /** @return the received OFErrorMsg that caused the error to be raised.
+     */
+    public OFErrorMsg getErrorMessage() {
+        return errorMessage;
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java
index c5adf4470..9a0348767 100644
--- a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java
+++ b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java
@@ -29,12 +29,12 @@ import java.util.concurrent.ScheduledExecutorService;
 
 import org.jboss.netty.buffer.ChannelBuffer;
 import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFType;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -226,9 +226,9 @@ public class OFMessageFilterManager
             OFPacketOut p = (OFPacketOut) m;
             
             // No MAC match if packetOut doesn't have the packet.
-            if (p.getPacketData() == null) return null;
+            if (p.getData() == null) return null;
             
-            eth.deserialize(p.getPacketData(), 0, p.getPacketData().length);
+            eth.deserialize(p.getData(), 0, p.getData().length);
         } else if (m.getType() == OFType.FLOW_MOD) {
             // flow-mod can't be matched by mac.
             return null;
diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitch.java b/src/main/java/net/floodlightcontroller/core/OFSwitch.java
new file mode 100644
index 000000000..38b5ddaa6
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/OFSwitch.java
@@ -0,0 +1,1131 @@
+/**
+*    Copyright 2012, Big Switch Networks, Inc.
+*    Originally created by David Erickson, Stanford University
+*
+*    Licensed under the Apache License, Version 2.0 (the "License"); you may
+*    not use this file except in compliance with the License. You may obtain
+*    a copy of the License at
+*
+*         http://www.apache.org/licenses/LICENSE-2.0
+*
+*    Unless required by applicable law or agreed to in writing, software
+*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+*    License for the specific language governing permissions and limitations
+*    under the License.
+**/
+
+package net.floodlightcontroller.core;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import javax.annotation.Nonnull;
+
+import net.floodlightcontroller.core.annotations.LogMessageDoc;
+import net.floodlightcontroller.core.internal.IOFSwitchManager;
+import net.floodlightcontroller.core.util.AppCookie;
+import net.floodlightcontroller.core.util.URIUtil;
+
+import org.projectfloodlight.openflow.protocol.OFActionType;
+import org.projectfloodlight.openflow.protocol.OFBsnControllerConnection;
+import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionState;
+import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsReply;
+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.OFFlowWildcards;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFPortReason;
+import org.projectfloodlight.openflow.protocol.OFPortState;
+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.OFVersion;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFAuxId;
+import org.projectfloodlight.openflow.types.OFPort;
+
+import net.floodlightcontroller.util.LinkedHashSetWrapper;
+import net.floodlightcontroller.util.OrderedCollection;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * This is the internal representation of an openflow switch.
+ */
+public class OFSwitch implements IOFSwitchBackend {
+    protected static final Logger log =
+            LoggerFactory.getLogger(OFSwitch.class);
+
+    protected final ConcurrentMap<Object, Object> attributes;
+    protected final IOFSwitchManager switchManager;
+
+    /* Switch features from initial featuresReply */
+    protected Set<OFCapabilities> capabilities;
+    protected long buffers;
+    protected Set<OFActionType> actions;
+    protected short tables;
+    protected final DatapathId datapathId;
+
+    private boolean startDriverHandshakeCalled = false;
+    private final Map<OFAuxId, IOFConnectionBackend> connections;
+    private volatile Map<URI, Map<OFAuxId, OFBsnControllerConnection>> controllerConnections;
+    protected OFFactory factory;
+
+    /**
+     * Members hidden from subclasses
+     */
+    private final PortManager portManager;
+
+    private volatile boolean connected;
+
+    private volatile OFControllerRole role;
+
+    private boolean flowTableFull = false;
+
+    protected SwitchDescription description;
+
+    private GenTableMap genTableMap;
+
+    private SwitchStatus status;
+
+    public static final int OFSWITCH_APP_ID = ident(5);
+
+    static {
+        AppCookie.registerApp(OFSwitch.OFSWITCH_APP_ID, "switch");
+    }
+
+    public OFSwitch(IOFConnectionBackend connection, @Nonnull OFFactory factory, @Nonnull IOFSwitchManager switchManager,
+            @Nonnull DatapathId datapathId) {
+        if(connection == null)
+            throw new NullPointerException("connection must not be null");
+        if(!connection.getAuxId().equals(OFAuxId.MAIN))
+            throw new IllegalArgumentException("connection must be the main connection");
+        if(factory == null)
+            throw new NullPointerException("factory must not be null");
+        if(switchManager == null)
+            throw new NullPointerException("switchManager must not be null");
+
+        this.connected = true;
+        this.factory = factory;
+        this.switchManager = switchManager;
+        this.datapathId = datapathId;
+        this.attributes = new ConcurrentHashMap<Object, Object>();
+        this.role = null;
+        this.description = new SwitchDescription();
+        this.portManager = new PortManager();
+        this.genTableMap = GenTableMap.empty();
+        this.status = SwitchStatus.HANDSHAKE;
+
+        // Connections
+        this.connections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>();
+        this.connections.put(connection.getAuxId(), connection);
+
+        // Switch's controller connection
+        this.controllerConnections = ImmutableMap.of();
+
+        // Defaults properties for an ideal switch
+        this.setAttribute(PROP_FASTWILDCARDS, EnumSet.allOf(OFFlowWildcards.class));
+        this.setAttribute(PROP_SUPPORTS_OFPP_FLOOD, Boolean.TRUE);
+        this.setAttribute(PROP_SUPPORTS_OFPP_TABLE, Boolean.TRUE);
+    }
+
+    private static int ident(int i) {
+        return i;
+    }
+
+    @Override
+    public OFFactory getOFFactory() {
+        return factory;
+    }
+
+    /**
+     * Manages the ports of this switch.
+     *
+     * Provides methods to query and update the stored ports. The class ensures
+     * that every port name and port number is unique. When updating ports
+     * the class checks if port number <-> port name mappings have change due
+     * to the update. If a new port P has number and port that are inconsistent
+     * with the previous mapping(s) the class will delete all previous ports
+     * with name or number of the new port and then add the new port.
+     *
+     * Port names are stored as-is but they are compared case-insensitive
+     *
+     * The methods that change the stored ports return a list of
+     * PortChangeEvents that represent the changes that have been applied
+     * to the port list so that IOFSwitchListeners can be notified about the
+     * changes.
+     *
+     * Implementation notes:
+     * - We keep several different representations of the ports to allow for
+     *   fast lookups
+     * - Ports are stored in unchangeable lists. When a port is modified new
+     *   data structures are allocated.
+     * - We use a read-write-lock for synchronization, so multiple readers are
+     *   allowed.
+     */
+    protected static class PortManager {
+        private final ReentrantReadWriteLock lock;
+        private List<OFPortDesc> portList;
+        private List<OFPortDesc> enabledPortList;
+        private List<OFPort> enabledPortNumbers;
+        private Map<OFPort,OFPortDesc> portsByNumber;
+        private Map<String,OFPortDesc> portsByName;
+
+        public PortManager() {
+            this.lock = new ReentrantReadWriteLock();
+            this.portList = Collections.emptyList();
+            this.enabledPortList = Collections.emptyList();
+            this.enabledPortNumbers = Collections.emptyList();
+            this.portsByName = Collections.emptyMap();
+            this.portsByNumber = Collections.emptyMap();
+        }
+
+        /**
+         * Set the internal data structure storing this switch's port
+         * to the ports specified by newPortsByNumber
+         *
+         * CALLER MUST HOLD WRITELOCK
+         *
+         * @param newPortsByNumber
+         * @throws IllegaalStateException if called without holding the
+         * writelock
+         */
+        private void updatePortsWithNewPortsByNumber(
+                Map<OFPort,OFPortDesc> newPortsByNumber) {
+            if (!lock.writeLock().isHeldByCurrentThread()) {
+                throw new IllegalStateException("Method called without " +
+                                                "holding writeLock");
+            }
+            Map<String,OFPortDesc> newPortsByName =
+                    new HashMap<String, OFPortDesc>();
+            List<OFPortDesc> newPortList =
+                    new ArrayList<OFPortDesc>();
+            List<OFPortDesc> newEnabledPortList =
+                    new ArrayList<OFPortDesc>();
+            List<OFPort> newEnabledPortNumbers = new ArrayList<OFPort>();
+
+            for(OFPortDesc p: newPortsByNumber.values()) {
+                newPortList.add(p);
+                newPortsByName.put(p.getName().toLowerCase(), p);
+                if (p.getState().contains(OFPortState.LIVE)) {
+                    newEnabledPortList.add(p);
+                    newEnabledPortNumbers.add(p.getPortNo());
+                }
+            }
+            portsByName = Collections.unmodifiableMap(newPortsByName);
+            portsByNumber =
+                    Collections.unmodifiableMap(newPortsByNumber);
+            enabledPortList =
+                    Collections.unmodifiableList(newEnabledPortList);
+            enabledPortNumbers =
+                    Collections.unmodifiableList(newEnabledPortNumbers);
+            portList = Collections.unmodifiableList(newPortList);
+        }
+
+        /**
+         * Handle a OFPortStatus delete message for the given port.
+         * Updates the internal port maps/lists of this switch and returns
+         * the PortChangeEvents caused by the delete. If the given port
+         * exists as it, it will be deleted. If the name<->number for the
+         * given port is inconsistent with the ports stored by this switch
+         * the method will delete all ports with the number or name of the
+         * given port.
+         *
+         * This method will increment error/warn counters and log
+         *
+         * @param delPort the port from the port status message that should
+         * be deleted.
+         * @return ordered collection of port changes applied to this switch
+         */
+        private OrderedCollection<PortChangeEvent>
+                handlePortStatusDelete(OFPortDesc delPort) {
+            OrderedCollection<PortChangeEvent> events =
+                    new LinkedHashSetWrapper<PortChangeEvent>();
+            lock.writeLock().lock();
+            try {
+                Map<OFPort,OFPortDesc> newPortByNumber =
+                        new HashMap<OFPort, OFPortDesc>(portsByNumber);
+                OFPortDesc prevPort =
+                        portsByNumber.get(delPort.getPortNo());
+                if (prevPort == null) {
+                    // so such port. Do we have a port with the name?
+                    prevPort = portsByName.get(delPort.getName());
+                    if (prevPort != null) {
+                        newPortByNumber.remove(prevPort.getPortNo());
+                        events.add(new PortChangeEvent(prevPort,
+                                                       PortChangeType.DELETE));
+                    }
+                } else if (prevPort.getName().equals(delPort.getName())) {
+                    // port exists with consistent name-number mapping
+                    newPortByNumber.remove(delPort.getPortNo());
+                    events.add(new PortChangeEvent(delPort,
+                                                   PortChangeType.DELETE));
+                } else {
+                    // port with same number exists but its name differs. This
+                    // is weird. The best we can do is to delete the existing
+                    // port(s) that have delPort's name and number.
+                    newPortByNumber.remove(delPort.getPortNo());
+                    events.add(new PortChangeEvent(prevPort,
+                                                   PortChangeType.DELETE));
+                    // is there another port that has delPort's name?
+                    prevPort = portsByName.get(delPort.getName().toLowerCase());
+                    if (prevPort != null) {
+                        newPortByNumber.remove(prevPort.getPortNo());
+                        events.add(new PortChangeEvent(prevPort,
+                                                       PortChangeType.DELETE));
+                    }
+                }
+                updatePortsWithNewPortsByNumber(newPortByNumber);
+                return events;
+            } finally {
+                lock.writeLock().unlock();
+            }
+        }
+
+        /**
+         * Handle a OFPortStatus message, update the internal data structures
+         * that store ports and return the list of OFChangeEvents.
+         *
+         * This method will increment error/warn counters and log
+         *
+         * @param ps
+         * @return
+         */
+        @SuppressFBWarnings(value="SF_SWITCH_FALLTHROUGH")
+        public OrderedCollection<PortChangeEvent> handlePortStatusMessage(OFPortStatus ps) {
+            if (ps == null) {
+                throw new NullPointerException("OFPortStatus message must " +
+                                               "not be null");
+            }
+            lock.writeLock().lock();
+            try {
+                OFPortDesc port = ps.getDesc();
+                OFPortReason reason = ps.getReason();
+                if (reason == null) {
+                    throw new IllegalArgumentException("Unknown PortStatus " +
+                            "reason code " + ps.getReason());
+                }
+
+                if (log.isDebugEnabled()) {
+                    log.debug("Handling OFPortStatus: {} for {}",
+                              reason, String.format("%s (%d)", port.getName(), port.getPortNo().getPortNumber()));
+                }
+
+                if (reason == OFPortReason.DELETE)
+                    return handlePortStatusDelete(port);
+
+                // We handle ADD and MODIFY the same way. Since OpenFlow
+                // doesn't specify what uniquely identifies a port the
+                // notion of ADD vs. MODIFY can also be hazy. So we just
+                // compare the new port to the existing ones.
+                Map<OFPort,OFPortDesc> newPortByNumber =
+                    new HashMap<OFPort, OFPortDesc>(portsByNumber);
+                OrderedCollection<PortChangeEvent> events = getSinglePortChanges(port);
+                for (PortChangeEvent e: events) {
+                    switch(e.type) {
+                        case DELETE:
+                            newPortByNumber.remove(e.port.getPortNo());
+                            break;
+                        case ADD:
+                            if (reason != OFPortReason.ADD) {
+                                // weird case
+                            }
+                            // fall through
+                        case DOWN:
+                        case OTHER_UPDATE:
+                        case UP:
+                            // update or add the port in the map
+                            newPortByNumber.put(e.port.getPortNo(), e.port);
+                            break;
+                    }
+                }
+                updatePortsWithNewPortsByNumber(newPortByNumber);
+                return events;
+            } finally {
+                lock.writeLock().unlock();
+            }
+
+        }
+
+        /**
+         * Given a new or modified port newPort, returns the list of
+         * PortChangeEvents to "transform" the current ports stored by
+         * this switch to include / represent the new port. The ports stored
+         * by this switch are <b>NOT</b> updated.
+         *
+         * This method acquires the readlock and is thread-safe by itself.
+         * Most callers will need to acquire the write lock before calling
+         * this method though (if the caller wants to update the ports stored
+         * by this switch)
+         *
+         * @param newPort the new or modified port.
+         * @return the list of changes
+         */
+        public OrderedCollection<PortChangeEvent>
+                getSinglePortChanges(OFPortDesc newPort) {
+            lock.readLock().lock();
+            try {
+                OrderedCollection<PortChangeEvent> events =
+                        new LinkedHashSetWrapper<PortChangeEvent>();
+                // Check if we have a port by the same number in our
+                // old map.
+                OFPortDesc prevPort =
+                        portsByNumber.get(newPort.getPortNo());
+                if (newPort.equals(prevPort)) {
+                    // nothing has changed
+                    return events;
+                }
+
+                if (prevPort != null &&
+                        prevPort.getName().equals(newPort.getName())) {
+                    // A simple modify of a exiting port
+                    // A previous port with this number exists and it's name
+                    // also matches the new port. Find the differences
+                    if (prevPort.getState().contains(OFPortState.LIVE) && !newPort.getState().contains(OFPortState.LIVE)) {
+                        events.add(new PortChangeEvent(newPort,
+                                                       PortChangeType.DOWN));
+                    } else if (!prevPort.getState().contains(OFPortState.LIVE) && newPort.getState().contains(OFPortState.LIVE)) {
+                        events.add(new PortChangeEvent(newPort,
+                                                       PortChangeType.UP));
+                    } else {
+                        events.add(new PortChangeEvent(newPort,
+                                   PortChangeType.OTHER_UPDATE));
+                    }
+                    return events;
+                }
+
+                if (prevPort != null) {
+                    // There exists a previous port with the same port
+                    // number but the port name is different (otherwise we would
+                    // never have gotten here)
+                    // Remove the port. Name-number mapping(s) have changed
+                    events.add(new PortChangeEvent(prevPort,
+                                                   PortChangeType.DELETE));
+                }
+
+                // We now need to check if there exists a previous port sharing
+                // the same name as the new/updated port.
+                prevPort = portsByName.get(newPort.getName().toLowerCase());
+                if (prevPort != null) {
+                    // There exists a previous port with the same port
+                    // name but the port number is different (otherwise we
+                    // never have gotten here).
+                    // Remove the port. Name-number mapping(s) have changed
+                    events.add(new PortChangeEvent(prevPort,
+                                                   PortChangeType.DELETE));
+                }
+
+                // We always need to add the new port. Either no previous port
+                // existed or we just deleted previous ports with inconsistent
+                // name-number mappings
+                events.add(new PortChangeEvent(newPort, PortChangeType.ADD));
+                return events;
+            } finally {
+                lock.readLock().unlock();
+            }
+        }
+
+        /**
+         * Compare the current ports of this switch to the newPorts list and
+         * return the changes that would be applied to transfort the current
+         * ports to the new ports. No internal data structures are updated
+         * see {@link #compareAndUpdatePorts(List, boolean)}
+         *
+         * @param newPorts the list of new ports
+         * @return The list of differences between the current ports and
+         * newPortList
+         */
+        public OrderedCollection<PortChangeEvent>
+                comparePorts(Collection<OFPortDesc> newPorts) {
+            return compareAndUpdatePorts(newPorts, false);
+        }
+
+        /**
+         * Compare the current ports of this switch to the newPorts list and
+         * return the changes that would be applied to transform the current
+         * ports to the new ports. No internal data structures are updated
+         * see {@link #compareAndUpdatePorts(List, boolean)}
+         *
+         * @param newPorts the list of new ports
+         * @return The list of differences between the current ports and
+         * newPortList
+         */
+        public OrderedCollection<PortChangeEvent>
+                updatePorts(Collection<OFPortDesc> newPorts) {
+            return compareAndUpdatePorts(newPorts, true);
+        }
+
+        /**
+         * Compare the current ports stored in this switch instance with the
+         * new port list given and return the differences in the form of
+         * PortChangeEvents. If the doUpdate flag is true, newPortList will
+         * replace the current list of this switch (and update the port maps)
+         *
+         * Implementation note:
+         * Since this method can optionally modify the current ports and
+         * since it's not possible to upgrade a read-lock to a write-lock
+         * we need to hold the write-lock for the entire operation. If this
+         * becomes a problem and if compares() are common we can consider
+         * splitting in two methods but this requires lots of code duplication
+         *
+         * @param newPorts the list of new ports.
+         * @param doUpdate If true the newPortList will replace the current
+         * port list for this switch. If false this switch will not be changed.
+         * @return The list of differences between the current ports and
+         * newPorts
+         * @throws NullPointerException if newPortsList is null
+         * @throws IllegalArgumentException if either port names or port numbers
+         * are duplicated in the newPortsList.
+         */
+        private OrderedCollection<PortChangeEvent> compareAndUpdatePorts(
+                Collection<OFPortDesc> newPorts,
+                boolean doUpdate) {
+            if (newPorts == null) {
+                throw new NullPointerException("newPortsList must not be null");
+            }
+            lock.writeLock().lock();
+            try {
+                OrderedCollection<PortChangeEvent> events =
+                        new LinkedHashSetWrapper<PortChangeEvent>();
+
+                Map<OFPort,OFPortDesc> newPortsByNumber =
+                        new HashMap<OFPort, OFPortDesc>();
+                Map<String,OFPortDesc> newPortsByName =
+                        new HashMap<String, OFPortDesc>();
+                List<OFPortDesc> newEnabledPortList =
+                        new ArrayList<OFPortDesc>();
+                List<OFPort> newEnabledPortNumbers =
+                        new ArrayList<OFPort>();
+                List<OFPortDesc> newPortsList =
+                        new ArrayList<OFPortDesc>(newPorts);
+
+                for (OFPortDesc p: newPortsList) {
+                    if (p == null) {
+                        throw new NullPointerException("portList must not " +
+                                "contain null values");
+                    }
+
+                    // Add the port to the new maps and lists and check
+                    // that every port is unique
+                    OFPortDesc duplicatePort;
+                    duplicatePort = newPortsByNumber.put(p.getPortNo(), p);
+                    if (duplicatePort != null) {
+                        String msg = String.format("Cannot have two ports " +
+                                "with the same number: %s <-> %s",
+                                String.format("%s (%d)", p.getName(), p.getPortNo().getPortNumber()),
+                                String.format("%s (%d)", duplicatePort.getName(), duplicatePort.getPortNo().getPortNumber()));
+                        throw new IllegalArgumentException(msg);
+                    }
+                    duplicatePort =
+                            newPortsByName.put(p.getName().toLowerCase(), p);
+                    if (duplicatePort != null) {
+                        String msg = String.format("Cannot have two ports " +
+                                "with the same name: %s <-> %s",
+                                String.format("%s (%d)", p.getName(), p.getPortNo().getPortNumber()),
+                                String.format("%s (%d)", duplicatePort.getName(), duplicatePort.getPortNo().getPortNumber()));
+                        throw new IllegalArgumentException(msg);
+                    }
+                    if (p.getState().contains(OFPortState.LIVE)) {
+                        newEnabledPortList.add(p);
+                        newEnabledPortNumbers.add(p.getPortNo());
+                    }
+
+                    // get changes
+                    events.addAll(getSinglePortChanges(p));
+                }
+                // find deleted ports
+                // We need to do this after looping through all the new ports
+                // to we can handle changed name<->number mappings correctly
+                // We could pull it into the loop of we address this but
+                // it's probably not worth it
+                for (OFPortDesc oldPort: this.portList) {
+                    if (!newPortsByNumber.containsKey(oldPort.getPortNo())) {
+                        PortChangeEvent ev =
+                                new PortChangeEvent(oldPort,
+                                                    PortChangeType.DELETE);
+                        events.add(ev);
+                    }
+                }
+
+
+                if (doUpdate) {
+                    portsByName = Collections.unmodifiableMap(newPortsByName);
+                    portsByNumber =
+                            Collections.unmodifiableMap(newPortsByNumber);
+                    enabledPortList =
+                            Collections.unmodifiableList(newEnabledPortList);
+                    enabledPortNumbers =
+                            Collections.unmodifiableList(newEnabledPortNumbers);
+                    portList = Collections.unmodifiableList(newPortsList);
+                }
+                return events;
+            } finally {
+                lock.writeLock().unlock();
+            }
+        }
+
+        public OFPortDesc getPort(String name) {
+            if (name == null) {
+                throw new NullPointerException("Port name must not be null");
+            }
+            lock.readLock().lock();
+            try {
+                return portsByName.get(name.toLowerCase());
+            } finally {
+                lock.readLock().unlock();
+            }
+        }
+
+        public OFPortDesc getPort(OFPort portNumber) {
+            lock.readLock().lock();
+            try {
+                return portsByNumber.get(portNumber);
+            } finally {
+                lock.readLock().unlock();
+            }
+        }
+
+        public List<OFPortDesc> getPorts() {
+            lock.readLock().lock();
+            try {
+                return portList;
+            } finally {
+                lock.readLock().unlock();
+            }
+        }
+
+        public List<OFPortDesc> getEnabledPorts() {
+            lock.readLock().lock();
+            try {
+                return enabledPortList;
+            } finally {
+                lock.readLock().unlock();
+            }
+        }
+
+        public List<OFPort> getEnabledPortNumbers() {
+            lock.readLock().lock();
+            try {
+                return enabledPortNumbers;
+            } finally {
+                lock.readLock().unlock();
+            }
+        }
+    }
+
+    @Override
+    public boolean attributeEquals(String name, Object other) {
+        Object attr = this.attributes.get(name);
+        if (attr == null)
+            return false;
+        return attr.equals(other);
+    }
+
+    @Override
+    public Object getAttribute(String name) {
+        // returns null if key doesn't exist
+        return this.attributes.get(name);
+    }
+
+    @Override
+    public void setAttribute(String name, Object value) {
+        this.attributes.put(name, value);
+        return;
+    }
+
+    @Override
+    public Object removeAttribute(String name) {
+        return this.attributes.remove(name);
+    }
+
+    @Override
+    public boolean hasAttribute(String name) {
+        return this.attributes.containsKey(name);
+    }
+
+    @Override
+    public void registerConnection(IOFConnectionBackend connection) {
+        this.connections.put(connection.getAuxId(), connection);
+    }
+
+
+    @Override
+    public ImmutableList<IOFConnection> getConnections() {
+        return ImmutableList.<IOFConnection> copyOf(this.connections.values());
+    }
+
+    @Override
+    public void removeConnections() {
+        this.connections.clear();
+    }
+
+    @Override
+    public void removeConnection(IOFConnectionBackend connection) {
+        this.connections.remove(connection.getAuxId());
+    }
+
+    @Override
+    public void write(OFMessage m) {
+        connections.get(OFAuxId.MAIN).write(m);
+    }
+
+    /**
+     * Gets a connection specified by aux Id.
+     * @param auxId the specified aux id for the connection desired.
+     * @return the aux connection specified by the auxId
+     */
+    public IOFConnection getConnection(OFAuxId auxId) {
+        IOFConnection connection = this.connections.get(auxId);
+        if(connection == null){
+            throw new IllegalArgumentException("OF Connection for " + this + " with " + auxId + " does not exist.");
+        }
+        return connection;
+    }
+
+    public IOFConnection getConnection(LogicalOFMessageCategory category) {
+        if(switchManager.isCategoryRegistered(category)){
+            return getConnection(category.getAuxId());
+        }
+        else{
+            throw new IllegalArgumentException(category + " is not registered with the floodlight provider service.");
+        }
+    }
+
+    @Override
+    public void write(OFMessage m, LogicalOFMessageCategory category) {
+        this.getConnection(category).write(m);
+    }
+
+    @Override
+    public void write(Iterable<OFMessage> msglist, LogicalOFMessageCategory category) {
+        this.getConnection(category).write(msglist);
+    }
+
+    @Override
+    public OFConnection getConnectionByCategory(LogicalOFMessageCategory category){
+        return (OFConnection) this.getConnection(category);
+    }
+
+    @Override
+    public <R extends OFMessage> ListenableFuture<R> writeRequest(OFRequest<R> request, LogicalOFMessageCategory category) {
+        return getConnection(category).writeRequest(request);
+    }
+
+    @Override
+    public <R extends OFMessage> ListenableFuture<R> writeRequest(OFRequest<R> request) {
+        return connections.get(OFAuxId.MAIN).writeRequest(request);
+    }
+
+    @Override
+    @LogMessageDoc(level="WARN",
+                   message="Sending OF message that modifies switch " +
+                           "state while in the slave role: {switch}",
+                   explanation="An application has sent a message to a switch " +
+                           "that is not valid when the switch is in a slave role",
+                   recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
+    public void write(Iterable<OFMessage> msglist) {
+        connections.get(OFAuxId.MAIN).write(msglist);
+    }
+
+    @Override
+    public void disconnect() {
+
+        // Iterate through connections and perform cleanup
+        for(Entry<OFAuxId, IOFConnectionBackend> entry : this.connections.entrySet()){
+            entry.getValue().disconnect();
+            this.connections.remove(entry.getKey());
+        }
+
+        connected = false;
+    }
+
+    @Override
+    public void setFeaturesReply(OFFeaturesReply featuresReply) {
+        if (portManager.getPorts().isEmpty() && featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) {
+            /* ports are updated via port status message, so we
+             * only fill in ports on initial connection.
+             */
+            List<OFPortDesc> OFPortDescs = featuresReply.getPorts();
+            portManager.updatePorts(OFPortDescs);
+        }
+        this.capabilities = featuresReply.getCapabilities();
+        this.buffers = featuresReply.getNBuffers();
+
+        if (featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0 ) {
+            // FIXME:LOJI: OF1.3 has per table actions. This needs to be modeled / handled here
+            this.actions = featuresReply.getActions();
+        }
+        this.tables = featuresReply.getNTables();
+    }
+
+    @Override
+    public void setPortDescStats(OFPortDescStatsReply reply) {
+        /* ports are updated via port status message, so we
+         * only fill in ports on initial connection.
+         */
+        List<OFPortDesc> OFPortDescs = reply.getEntries();
+        portManager.updatePorts(OFPortDescs);
+    }
+
+    @Override
+    public Collection<OFPortDesc> getEnabledPorts() {
+        return portManager.getEnabledPorts();
+    }
+
+    @Override
+    public Collection<OFPort> getEnabledPortNumbers() {
+        return portManager.getEnabledPortNumbers();
+    }
+
+    @Override
+    public OFPortDesc getPort(OFPort portNumber) {
+        return portManager.getPort(portNumber);
+    }
+
+    @Override
+    public OFPortDesc getPort(String portName) {
+        return portManager.getPort(portName);
+    }
+
+    @Override
+    public OrderedCollection<PortChangeEvent>
+            processOFPortStatus(OFPortStatus ps) {
+        return portManager.handlePortStatusMessage(ps);
+    }
+
+    @Override
+    public Collection<OFPortDesc> getSortedPorts() {
+        // FIXME: Hopefully BigDB will handle this automatically soon (or not
+        // have the sorting requirement), in which case we could get rid of this
+        List<OFPortDesc> sortedPorts =
+                new ArrayList<OFPortDesc>(portManager.getPorts());
+        Collections.sort(sortedPorts, new Comparator<OFPortDesc>() {
+            @Override
+            public int compare(OFPortDesc o1, OFPortDesc o2) {
+                String name1 = o1.getName();
+                String name2 = o2.getName();
+                return name1.compareToIgnoreCase(name2);
+            }
+        });
+        return sortedPorts;
+    }
+
+    @Override
+    public Collection<OFPortDesc> getPorts() {
+        return portManager.getPorts();
+    }
+
+    @Override
+    public OrderedCollection<PortChangeEvent>
+            comparePorts(Collection<OFPortDesc> ports) {
+        return portManager.comparePorts(ports);
+    }
+
+    @Override
+    public OrderedCollection<PortChangeEvent>
+            setPorts(Collection<OFPortDesc> ports) {
+        return portManager.updatePorts(ports);
+    }
+
+    @Override
+    public boolean portEnabled(OFPort portNumber) {
+        OFPortDesc p = portManager.getPort(portNumber);
+        if (p == null) return false;
+        return p.getState().contains(OFPortState.LIVE);
+    }
+
+    @Override
+    public boolean portEnabled(String portName) {
+        OFPortDesc p = portManager.getPort(portName);
+        if (p == null) return false;
+        return p.getState().contains(OFPortState.LIVE);
+    }
+
+    @Override
+    public DatapathId getId() {
+        if (datapathId == null)
+            throw new RuntimeException("Features reply has not yet been set");
+        return datapathId;
+    }
+
+    @Override
+    public String getStringId() {
+        // FIXME: Should get rid of this
+        return getId().toString();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "OFSwitchBase DPID[" + ((datapathId != null) ? datapathId.toString() : "?") + "]";
+    }
+
+    @Override
+    public ConcurrentMap<Object, Object> getAttributes() {
+        return this.attributes;
+    }
+
+    @Override
+    public Date getConnectedSince() {
+        return this.connections.get(OFAuxId.MAIN).getConnectedSince();
+    }
+
+    @Override
+    public <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest(OFStatsRequest<REPLY> request) {
+        return connections.get(OFAuxId.MAIN).writeStatsRequest(request);
+    }
+
+    @Override
+    public <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest(OFStatsRequest<REPLY> request, LogicalOFMessageCategory category) {
+        return getConnection(category).writeStatsRequest(request);
+    }
+
+    @Override
+    public void cancelAllPendingRequests() {
+        for(Entry<OFAuxId, IOFConnectionBackend> entry : this.connections.entrySet()){
+            entry.getValue().cancelAllPendingRequests();
+        }
+    }
+
+    // If any connections are down consider a switch disconnected
+    @Override
+    public boolean isConnected() {
+        return connected;
+    }
+
+    @Override
+    public boolean isActive() {
+        // no lock needed since we use volatile
+        return isConnected() && this.role == OFControllerRole.ROLE_MASTER;
+    }
+
+    @Override
+    public OFControllerRole getControllerRole() {
+        return role;
+    }
+
+    @Override
+    public void setControllerRole(OFControllerRole role) {
+        this.role = role;
+    }
+
+    @Override
+    public void flush() {
+        for(Entry<OFAuxId, IOFConnectionBackend> entry : this.connections.entrySet()){
+            entry.getValue().flush();
+        }
+    }
+
+    /**
+     * Get the IP Address for the switch
+     * @return the inet address
+     */
+    @Override
+    public SocketAddress getInetAddress() {
+        return connections.get(OFAuxId.MAIN).getRemoteInetAddress();
+    }
+
+    @Override
+    public long getBuffers() {
+        return buffers;
+    }
+
+
+    @Override
+    public Set<OFActionType> getActions() {
+        return actions;
+    }
+
+
+    @Override
+    public Set<OFCapabilities> getCapabilities() {
+        return capabilities;
+    }
+
+
+    @Override
+    public short getTables() {
+        return tables;
+    }
+
+    @Override
+    public SwitchDescription getSwitchDescription() {
+        return description;
+    }
+
+    @Override
+    @LogMessageDoc(level="WARN",
+        message="Switch {switch} flow table is full",
+        explanation="The controller received flow table full " +
+                "message from the switch, could be caused by increased " +
+                "traffic pattern",
+                recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
+    public void setTableFull(boolean isFull) {
+        if (isFull && !flowTableFull) {
+            switchManager.addSwitchEvent(this.datapathId,
+                    "SWITCH_FLOW_TABLE_FULL " +
+                    "Table full error from switch", false);
+            log.warn("Switch {} flow table is full", datapathId.toString());
+        }
+        flowTableFull = isFull;
+    }
+
+    @Override
+    public void startDriverHandshake() {
+        if (startDriverHandshakeCalled)
+            throw new SwitchDriverSubHandshakeAlreadyStarted();
+        startDriverHandshakeCalled = true;
+    }
+
+    @Override
+    public boolean isDriverHandshakeComplete() {
+        if (!startDriverHandshakeCalled)
+            throw new SwitchDriverSubHandshakeNotStarted();
+        return true;
+    }
+
+    @Override
+    public void processDriverHandshakeMessage(OFMessage m) {
+        if (startDriverHandshakeCalled)
+            throw new SwitchDriverSubHandshakeCompleted(m);
+        else
+            throw new SwitchDriverSubHandshakeNotStarted();
+    }
+
+    @Override
+    public GenTableMap getGenTableMap() {
+        return genTableMap;
+    }
+
+    @Override
+    public void setGenTableMap(GenTableMap map) {
+        this.genTableMap = map;
+    }
+
+    @Override
+    public void setSwitchProperties(SwitchDescription description) {
+        this.description = description;
+    }
+
+
+    @Override
+    public SwitchStatus getStatus() {
+        return status;
+    }
+
+    @Override
+    public void setStatus(SwitchStatus switchStatus) {
+        this.status = switchStatus;
+    }
+
+    /**
+     * Can the port be turned on without forming a new loop?
+     * <p>
+     * <b>FIXME</b> - This API is deprecated and will be removed soon. The
+     * property is currently not implemented by the platform, so this method
+     * always returns false. Whether or not a port is safe to use is dependent
+     * on the application strategy for forwarding traffic.
+     *
+     * @param port_num the port number to be tested
+     * @return always false for now.
+     */
+    @Deprecated
+    @Override
+    public boolean isFastPort(OFPort port_num) {
+        return false;
+    }
+
+    @Override
+    public void updateControllerConnections(OFBsnControllerConnectionsReply controllerCxnsReply) {
+
+        // Instantiate clean map, can't use a builder here since we need to call temp.get()
+        Map<URI,Map<OFAuxId, OFBsnControllerConnection>> temp = new ConcurrentHashMap<URI,Map<OFAuxId, OFBsnControllerConnection>>();
+
+        List<OFBsnControllerConnection> controllerCxnUpdates = controllerCxnsReply.getConnections();
+        for(OFBsnControllerConnection update : controllerCxnUpdates) {
+            URI uri = URI.create(update.getUri());
+
+            Map<OFAuxId, OFBsnControllerConnection> cxns = temp.get(uri);
+
+            // Add to nested map
+            if(cxns != null){
+                cxns.put(update.getAuxiliaryId(), update);
+            } else{
+                cxns = new ConcurrentHashMap<OFAuxId, OFBsnControllerConnection>();
+                cxns.put(update.getAuxiliaryId(), update);
+                temp.put(uri, cxns);
+            }
+        }
+
+        this.controllerConnections = ImmutableMap.<URI,Map<OFAuxId, OFBsnControllerConnection>>copyOf(temp);
+    }
+
+    @Override
+    public boolean hasAnotherMaster() {
+
+        //TODO: refactor get connection to not throw illegal arg exceptions
+        IOFConnection mainCxn = this.getConnection(OFAuxId.MAIN);
+
+        if(mainCxn != null) {
+
+            // Determine the local URI
+            InetSocketAddress address = (InetSocketAddress) mainCxn.getLocalInetAddress();
+            URI localURI = URIUtil.createURI(address.getHostName(), address.getPort());
+
+            for(Entry<URI,Map<OFAuxId, OFBsnControllerConnection>> entry : this.controllerConnections.entrySet()) {
+
+                // Don't check our own controller connections
+                URI uri = entry.getKey();
+                if(!localURI.equals(uri)){
+
+                    // We only care for the MAIN connection
+                    Map<OFAuxId, OFBsnControllerConnection> cxns = this.controllerConnections.get(uri);
+                    OFBsnControllerConnection controllerCxn = cxns.get(OFAuxId.MAIN);
+
+                    if(controllerCxn != null) {
+                        // If the controller id disconnected or not master we know it is not connected
+                        if(controllerCxn.getState() == OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED
+                                && controllerCxn.getRole() == OFControllerRole.ROLE_MASTER){
+                            return true;
+                        }
+                    } else {
+                        log.warn("Unable to find controller connection with aux id "
+                                + "MAIN for switch {} on controller with URI {}.",
+                                  this, uri);
+                    }
+                }
+            }
+        }
+       return false;
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java b/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java
deleted file mode 100644
index 1fb321bad..000000000
--- a/src/main/java/net/floodlightcontroller/core/OFSwitchBase.java
+++ /dev/null
@@ -1,1579 +0,0 @@
-/**
-*    Copyright 2012, Big Switch Networks, Inc.
-*    Originally created by David Erickson, Stanford University
-*
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core;
-
-import java.io.IOException;
-import java.net.SocketAddress;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Future;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import net.floodlightcontroller.core.IFloodlightProviderService.Role;
-import net.floodlightcontroller.core.annotations.LogMessageDoc;
-import net.floodlightcontroller.core.annotations.LogMessageDocs;
-import net.floodlightcontroller.core.internal.Controller;
-import net.floodlightcontroller.core.internal.OFFeaturesReplyFuture;
-import net.floodlightcontroller.core.internal.OFStatisticsFuture;
-import net.floodlightcontroller.core.util.AppCookie;
-import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
-import net.floodlightcontroller.debugcounter.IDebugCounter;
-import net.floodlightcontroller.debugcounter.IDebugCounterService;
-import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
-import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
-import net.floodlightcontroller.debugcounter.NullDebugCounter;
-import net.floodlightcontroller.devicemanager.SwitchPort;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.routing.ForwardingBase;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-import net.floodlightcontroller.util.LinkedHashSetWrapper;
-import net.floodlightcontroller.util.MACAddress;
-import net.floodlightcontroller.util.OrderedCollection;
-import net.floodlightcontroller.util.TimedCache;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-
-import org.jboss.netty.channel.Channel;
-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.OFPortStatus;
-import org.openflow.protocol.OFPortStatus.OFPortReason;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFStatisticsReply;
-import org.openflow.protocol.OFStatisticsRequest;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
-import org.openflow.protocol.statistics.OFStatistics;
-import org.openflow.protocol.statistics.OFStatisticsType;
-import org.openflow.protocol.statistics.OFTableStatistics;
-import org.openflow.util.HexString;
-import org.openflow.util.U16;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This is the internal representation of an openflow switch.
- */
-public abstract class OFSwitchBase implements IOFSwitch {
-    // TODO: should we really do logging in the class or should we throw
-    // exception that can then be handled by callers?
-    protected static final Logger log = LoggerFactory.getLogger(OFSwitchBase.class);
-
-    protected ConcurrentMap<Object, Object> attributes;
-    protected IFloodlightProviderService floodlightProvider;
-    protected IThreadPoolService threadPool;
-    protected IDebugCounterService debugCounters;
-    // FIXME: Don't use java.util.Date
-    protected volatile Date connectedSince;
-
-    /* Switch features from initial featuresReply */
-    protected int capabilities;
-    protected int buffers;
-    protected int actions;
-    protected byte tables;
-    protected long datapathId;
-    protected String stringId;
-
-    protected short accessFlowPriority;
-    protected short coreFlowPriority;
-
-    private boolean startDriverHandshakeCalled = false;
-    protected Channel channel;
-
-    /**
-     * Members hidden from subclasses
-     */
-    private final AtomicInteger transactionIdSource;
-    private final Map<Integer,OFStatisticsFuture> statsFutureMap;
-    private final Map<Integer, IOFMessageListener> iofMsgListenersMap;
-    private final Map<Integer,OFFeaturesReplyFuture> featuresFutureMap;
-    private volatile boolean connected;
-    private volatile Role role;
-    private final TimedCache<Long> timedCache;
-    private final ConcurrentMap<Short, AtomicLong> portBroadcastCacheHitMap;
-
-    private final PortManager portManager;
-
-    // Private members for throttling
-    private boolean writeThrottleEnabled = false;
-    protected boolean packetInThrottleEnabled = false; // used by test
-    private int packetInRateThresholdHigh =
-            Integer.parseInt(System.getProperty("input_threshold", "1000"));
-    private int packetInRateThresholdLow = 1;
-    private int packetInRatePerMacThreshold = 50;
-    private int packetInRatePerPortThreshold = 100;
-    private long messageCount = 0;
-    private long messageCountUniqueOFMatch = 0;
-    private long lastMessageTime;
-    private int currentRate = 0;
-    private TimedCache<OFMatch> ofMatchCache;
-    private TimedCache<Long> macCache;
-    private TimedCache<Long> macBlockedCache;
-    private TimedCache<Short> portCache;
-    private TimedCache<Short> portBlockedCache;
-    private boolean flowTableFull = false;
-
-    protected OFDescriptionStatistics description;
-
-    private boolean debugCountersRegistered;
-    @SuppressWarnings("unused")
-    private IDebugCounter ctrSwitch, ctrSwitchPktin, ctrSwitchWrite;
-    private IDebugCounter ctrSwitchPktinDrops, ctrSwitchWriteDrops;
-
-    private static final String PACKAGE = OFSwitchBase.class.getPackage().getName();
-
-
-    protected final static ThreadLocal<Map<IOFSwitch,List<OFMessage>>> local_msg_buffer =
-            new ThreadLocal<Map<IOFSwitch,List<OFMessage>>>() {
-        @Override
-        protected Map<IOFSwitch,List<OFMessage>> initialValue() {
-            return new HashMap<IOFSwitch,List<OFMessage>>();
-        }
-    };
-
-    public static final int OFSWITCH_APP_ID = 5;
-    static {
-        AppCookie.registerApp(OFSwitchBase.OFSWITCH_APP_ID, "switch");
-    }
-
-    public OFSwitchBase() {
-        this.stringId = null;
-        this.attributes = new ConcurrentHashMap<Object, Object>();
-        this.connectedSince = null;
-        this.transactionIdSource = new AtomicInteger();
-        this.connected = false;
-        this.statsFutureMap = new ConcurrentHashMap<Integer,OFStatisticsFuture>();
-        this.featuresFutureMap = new ConcurrentHashMap<Integer,OFFeaturesReplyFuture>();
-        this.iofMsgListenersMap = new ConcurrentHashMap<Integer,IOFMessageListener>();
-        this.role = null;
-        this.timedCache = new TimedCache<Long>(100, 5*1000 );  // 5 seconds interval
-        this.portBroadcastCacheHitMap = new ConcurrentHashMap<Short, AtomicLong>();
-        this.description = new OFDescriptionStatistics();
-        this.lastMessageTime = System.currentTimeMillis();
-
-        this.portManager = new PortManager();
-
-        // Defaults properties for an ideal switch
-        this.setAttribute(PROP_FASTWILDCARDS, OFMatch.OFPFW_ALL);
-        this.setAttribute(PROP_SUPPORTS_OFPP_FLOOD, Boolean.valueOf(true));
-        this.setAttribute(PROP_SUPPORTS_OFPP_TABLE, Boolean.valueOf(true));
-        if (packetInRateThresholdHigh == 0) {
-            packetInRateThresholdHigh = Integer.MAX_VALUE;
-        } else {
-            packetInRateThresholdLow = packetInRateThresholdHigh / 2;
-        }
-    }
-
-
-
-    /**
-     * Manages the ports of this switch.
-     *
-     * Provides methods to query and update the stored ports. The class ensures
-     * that every port name and port number is unique. When updating ports
-     * the class checks if port number <-> port name mappings have change due
-     * to the update. If a new port P has number and port that are inconsistent
-     * with the previous mapping(s) the class will delete all previous ports
-     * with name or number of the new port and then add the new port.
-     *
-     * Port names are stored as-is but they are compared case-insensitive
-     *
-     * The methods that change the stored ports return a list of
-     * PortChangeEvents that represent the changes that have been applied
-     * to the port list so that IOFSwitchListeners can be notified about the
-     * changes.
-     *
-     * Implementation notes:
-     * - We keep several different representations of the ports to allow for
-     *   fast lookups
-     * - Ports are stored in unchangeable lists. When a port is modified new
-     *   data structures are allocated.
-     * - We use a read-write-lock for synchronization, so multiple readers are
-     *   allowed.
-     */
-    protected class PortManager {
-        private final ReentrantReadWriteLock lock;
-        private List<ImmutablePort> portList;
-        private List<ImmutablePort> enabledPortList;
-        private List<Short> enabledPortNumbers;
-        private Map<Short,ImmutablePort> portsByNumber;
-        private Map<String,ImmutablePort> portsByName;
-
-
-
-
-        public PortManager() {
-            this.lock = new ReentrantReadWriteLock();
-            this.portList = Collections.emptyList();
-            this.enabledPortList = Collections.emptyList();
-            this.enabledPortNumbers = Collections.emptyList();
-            this.portsByName = Collections.emptyMap();
-            this.portsByNumber = Collections.emptyMap();
-        }
-
-        /**
-         * Set the internal data structure storing this switch's port
-         * to the ports specified by newPortsByNumber
-         *
-         * CALLER MUST HOLD WRITELOCK
-         *
-         * @param newPortsByNumber
-         * @throws IllegaalStateException if called without holding the
-         * writelock
-         */
-        private void updatePortsWithNewPortsByNumber(
-                Map<Short,ImmutablePort> newPortsByNumber) {
-            if (!lock.writeLock().isHeldByCurrentThread()) {
-                throw new IllegalStateException("Method called without " +
-                                                "holding writeLock");
-            }
-            Map<String,ImmutablePort> newPortsByName =
-                    new HashMap<String, ImmutablePort>();
-            List<ImmutablePort> newPortList =
-                    new ArrayList<ImmutablePort>();
-            List<ImmutablePort> newEnabledPortList =
-                    new ArrayList<ImmutablePort>();
-            List<Short> newEnabledPortNumbers = new ArrayList<Short>();
-
-            for(ImmutablePort p: newPortsByNumber.values()) {
-                newPortList.add(p);
-                newPortsByName.put(p.getName().toLowerCase(), p);
-                if (p.isEnabled()) {
-                    newEnabledPortList.add(p);
-                    newEnabledPortNumbers.add(p.getPortNumber());
-                }
-            }
-            portsByName = Collections.unmodifiableMap(newPortsByName);
-            portsByNumber =
-                    Collections.unmodifiableMap(newPortsByNumber);
-            enabledPortList =
-                    Collections.unmodifiableList(newEnabledPortList);
-            enabledPortNumbers =
-                    Collections.unmodifiableList(newEnabledPortNumbers);
-            portList = Collections.unmodifiableList(newPortList);
-        }
-
-        /**
-         * Handle a OFPortStatus delete message for the given port.
-         * Updates the internal port maps/lists of this switch and returns
-         * the PortChangeEvents caused by the delete. If the given port
-         * exists as it, it will be deleted. If the name<->number for the
-         * given port is inconsistent with the ports stored by this switch
-         * the method will delete all ports with the number or name of the
-         * given port.
-         *
-         * This method will increment error/warn counters and log
-         *
-         * @param delPort the port from the port status message that should
-         * be deleted.
-         * @return ordered collection of port changes applied to this switch
-         */
-        private OrderedCollection<PortChangeEvent>
-                handlePortStatusDelete(ImmutablePort delPort) {
-            lock.writeLock().lock();
-            OrderedCollection<PortChangeEvent> events =
-                    new LinkedHashSetWrapper<PortChangeEvent>();
-            try {
-                Map<Short,ImmutablePort> newPortByNumber =
-                        new HashMap<Short, ImmutablePort>(portsByNumber);
-                ImmutablePort prevPort =
-                        portsByNumber.get(delPort.getPortNumber());
-                if (prevPort == null) {
-                    // so such port. Do we have a port with the name?
-                    prevPort = portsByName.get(delPort.getName());
-                    if (prevPort != null) {
-                        newPortByNumber.remove(prevPort.getPortNumber());
-                        events.add(new PortChangeEvent(prevPort,
-                                                       PortChangeType.DELETE));
-                    }
-                } else if (prevPort.getName().equals(delPort.getName())) {
-                    // port exists with consistent name-number mapping
-                    newPortByNumber.remove(delPort.getPortNumber());
-                    events.add(new PortChangeEvent(delPort,
-                                                   PortChangeType.DELETE));
-                } else {
-                    // port with same number exists but its name differs. This
-                    // is weird. The best we can do is to delete the existing
-                    // port(s) that have delPort's name and number.
-                    newPortByNumber.remove(delPort.getPortNumber());
-                    events.add(new PortChangeEvent(prevPort,
-                                                   PortChangeType.DELETE));
-                    // is there another port that has delPort's name?
-                    prevPort = portsByName.get(delPort.getName().toLowerCase());
-                    if (prevPort != null) {
-                        newPortByNumber.remove(prevPort.getPortNumber());
-                        events.add(new PortChangeEvent(prevPort,
-                                                       PortChangeType.DELETE));
-                    }
-                }
-                updatePortsWithNewPortsByNumber(newPortByNumber);
-                return events;
-            } finally {
-                lock.writeLock().unlock();
-            }
-        }
-
-        /**
-         * Handle a OFPortStatus message, update the internal data structures
-         * that store ports and return the list of OFChangeEvents.
-         *
-         * This method will increment error/warn counters and log
-         *
-         * @param ps
-         * @return
-         */
-        public OrderedCollection<PortChangeEvent> handlePortStatusMessage(OFPortStatus ps) {
-            if (ps == null) {
-                throw new NullPointerException("OFPortStatus message must " +
-                                               "not be null");
-            }
-            lock.writeLock().lock();
-            try {
-                ImmutablePort port =
-                        ImmutablePort.fromOFPhysicalPort(ps.getDesc());
-                OFPortReason reason = OFPortReason.fromReasonCode(ps.getReason());
-                if (reason == null) {
-                    throw new IllegalArgumentException("Unknown PortStatus " +
-                            "reason code " + ps.getReason());
-                }
-
-                if (log.isDebugEnabled()) {
-                    log.debug("Handling OFPortStatus: {} for {}",
-                              reason, port.toBriefString());
-                }
-
-                if (reason == OFPortReason.OFPPR_DELETE)
-                        return handlePortStatusDelete(port);
-
-                // We handle ADD and MODIFY the same way. Since OpenFlow
-                // doesn't specify what uniquely identifies a port the
-                // notion of ADD vs. MODIFY can also be hazy. So we just
-                // compare the new port to the existing ones.
-                Map<Short,ImmutablePort> newPortByNumber =
-                    new HashMap<Short, ImmutablePort>(portsByNumber);
-                OrderedCollection<PortChangeEvent> events = getSinglePortChanges(port);
-                for (PortChangeEvent e: events) {
-                    switch(e.type) {
-                        case DELETE:
-                            newPortByNumber.remove(e.port.getPortNumber());
-                            break;
-                        case ADD:
-                            if (reason != OFPortReason.OFPPR_ADD) {
-                                // weird case
-                            }
-                            // fall through
-                        case DOWN:
-                        case OTHER_UPDATE:
-                        case UP:
-                            // update or add the port in the map
-                            newPortByNumber.put(e.port.getPortNumber(), e.port);
-                            break;
-                    }
-                }
-                updatePortsWithNewPortsByNumber(newPortByNumber);
-                return events;
-            } finally {
-                lock.writeLock().unlock();
-            }
-
-        }
-
-        /**
-         * Given a new or modified port newPort, returns the list of
-         * PortChangeEvents to "transform" the current ports stored by
-         * this switch to include / represent the new port. The ports stored
-         * by this switch are <b>NOT</b> updated.
-         *
-         * This method acquires the readlock and is thread-safe by itself.
-         * Most callers will need to acquire the write lock before calling
-         * this method though (if the caller wants to update the ports stored
-         * by this switch)
-         *
-         * @param newPort the new or modified port.
-         * @return the list of changes
-         */
-        public OrderedCollection<PortChangeEvent>
-                getSinglePortChanges(ImmutablePort newPort) {
-            lock.readLock().lock();
-            try {
-                OrderedCollection<PortChangeEvent> events =
-                        new LinkedHashSetWrapper<PortChangeEvent>();
-                // Check if we have a port by the same number in our
-                // old map.
-                ImmutablePort prevPort =
-                        portsByNumber.get(newPort.getPortNumber());
-                if (newPort.equals(prevPort)) {
-                    // nothing has changed
-                    return events;
-                }
-
-                if (prevPort != null &&
-                        prevPort.getName().equals(newPort.getName())) {
-                    // A simple modify of a exiting port
-                    // A previous port with this number exists and it's name
-                    // also matches the new port. Find the differences
-                    if (prevPort.isEnabled() && !newPort.isEnabled()) {
-                        events.add(new PortChangeEvent(newPort,
-                                                       PortChangeType.DOWN));
-                    } else if (!prevPort.isEnabled() && newPort.isEnabled()) {
-                        events.add(new PortChangeEvent(newPort,
-                                                       PortChangeType.UP));
-                    } else {
-                        events.add(new PortChangeEvent(newPort,
-                                   PortChangeType.OTHER_UPDATE));
-                    }
-                    return events;
-                }
-
-                if (prevPort != null) {
-                    // There exists a previous port with the same port
-                    // number but the port name is different (otherwise we would
-                    // never have gotten here)
-                    // Remove the port. Name-number mapping(s) have changed
-                    events.add(new PortChangeEvent(prevPort,
-                                                   PortChangeType.DELETE));
-                }
-
-                // We now need to check if there exists a previous port sharing
-                // the same name as the new/updated port.
-                prevPort = portsByName.get(newPort.getName().toLowerCase());
-                if (prevPort != null) {
-                    // There exists a previous port with the same port
-                    // name but the port number is different (otherwise we
-                    // never have gotten here).
-                    // Remove the port. Name-number mapping(s) have changed
-                    events.add(new PortChangeEvent(prevPort,
-                                                   PortChangeType.DELETE));
-                }
-
-                // We always need to add the new port. Either no previous port
-                // existed or we just deleted previous ports with inconsistent
-                // name-number mappings
-                events.add(new PortChangeEvent(newPort, PortChangeType.ADD));
-                return events;
-            } finally {
-                lock.readLock().unlock();
-            }
-        }
-
-        /**
-         * Compare the current ports of this switch to the newPorts list and
-         * return the changes that would be applied to transfort the current
-         * ports to the new ports. No internal data structures are updated
-         * see {@link #compareAndUpdatePorts(List, boolean)}
-         *
-         * @param newPorts the list of new ports
-         * @return The list of differences between the current ports and
-         * newPortList
-         */
-        public OrderedCollection<PortChangeEvent>
-                comparePorts(Collection<ImmutablePort> newPorts) {
-            return compareAndUpdatePorts(newPorts, false);
-        }
-
-        /**
-         * Compare the current ports of this switch to the newPorts list and
-         * return the changes that would be applied to transform the current
-         * ports to the new ports. No internal data structures are updated
-         * see {@link #compareAndUpdatePorts(List, boolean)}
-         *
-         * @param newPorts the list of new ports
-         * @return The list of differences between the current ports and
-         * newPortList
-         */
-        public OrderedCollection<PortChangeEvent>
-                updatePorts(Collection<ImmutablePort> newPorts) {
-            return compareAndUpdatePorts(newPorts, true);
-        }
-
-        /**
-         * Compare the current ports stored in this switch instance with the
-         * new port list given and return the differences in the form of
-         * PortChangeEvents. If the doUpdate flag is true, newPortList will
-         * replace the current list of this switch (and update the port maps)
-         *
-         * Implementation note:
-         * Since this method can optionally modify the current ports and
-         * since it's not possible to upgrade a read-lock to a write-lock
-         * we need to hold the write-lock for the entire operation. If this
-         * becomes a problem and if compares() are common we can consider
-         * splitting in two methods but this requires lots of code duplication
-         *
-         * @param newPorts the list of new ports.
-         * @param doUpdate If true the newPortList will replace the current
-         * port list for this switch. If false this switch will not be changed.
-         * @return The list of differences between the current ports and
-         * newPorts
-         * @throws NullPointerException if newPortsList is null
-         * @throws IllegalArgumentException if either port names or port numbers
-         * are duplicated in the newPortsList.
-         */
-        private OrderedCollection<PortChangeEvent> compareAndUpdatePorts(
-                Collection<ImmutablePort> newPorts,
-                boolean doUpdate) {
-            if (newPorts == null) {
-                throw new NullPointerException("newPortsList must not be null");
-            }
-            lock.writeLock().lock();
-            try {
-                OrderedCollection<PortChangeEvent> events =
-                        new LinkedHashSetWrapper<PortChangeEvent>();
-
-                Map<Short,ImmutablePort> newPortsByNumber =
-                        new HashMap<Short, ImmutablePort>();
-                Map<String,ImmutablePort> newPortsByName =
-                        new HashMap<String, ImmutablePort>();
-                List<ImmutablePort> newEnabledPortList =
-                        new ArrayList<ImmutablePort>();
-                List<Short> newEnabledPortNumbers =
-                        new ArrayList<Short>();
-                List<ImmutablePort> newPortsList =
-                        new ArrayList<ImmutablePort>(newPorts);
-
-                for (ImmutablePort p: newPortsList) {
-                    if (p == null) {
-                        throw new NullPointerException("portList must not " +
-                                "contain null values");
-                    }
-
-                    // Add the port to the new maps and lists and check
-                    // that every port is unique
-                    ImmutablePort duplicatePort;
-                    duplicatePort = newPortsByNumber.put(p.getPortNumber(), p);
-                    if (duplicatePort != null) {
-                        String msg = String.format("Cannot have two ports " +
-                                "with the same number: %s <-> %s",
-                                p.toBriefString(),
-                                duplicatePort.toBriefString());
-                        throw new IllegalArgumentException(msg);
-                    }
-                    duplicatePort =
-                            newPortsByName.put(p.getName().toLowerCase(), p);
-                    if (duplicatePort != null) {
-                        String msg = String.format("Cannot have two ports " +
-                                "with the same name: %s <-> %s",
-                                p.toBriefString(),
-                                duplicatePort.toBriefString());
-                        throw new IllegalArgumentException(msg);
-                    }
-                    if (p.isEnabled()) {
-                        newEnabledPortList.add(p);
-                        newEnabledPortNumbers.add(p.getPortNumber());
-                    }
-
-                    // get changes
-                    events.addAll(getSinglePortChanges(p));
-                }
-                // find deleted ports
-                // We need to do this after looping through all the new ports
-                // to we can handle changed name<->number mappings correctly
-                // We could pull it into the loop of we address this but
-                // it's probably not worth it
-                for (ImmutablePort oldPort: this.portList) {
-                    if (!newPortsByNumber.containsKey(oldPort.getPortNumber())) {
-                        PortChangeEvent ev =
-                                new PortChangeEvent(oldPort,
-                                                    PortChangeType.DELETE);
-                        events.add(ev);
-                    }
-                }
-
-
-                if (doUpdate) {
-                    portsByName = Collections.unmodifiableMap(newPortsByName);
-                    portsByNumber =
-                            Collections.unmodifiableMap(newPortsByNumber);
-                    enabledPortList =
-                            Collections.unmodifiableList(newEnabledPortList);
-                    enabledPortNumbers =
-                            Collections.unmodifiableList(newEnabledPortNumbers);
-                    portList = Collections.unmodifiableList(newPortsList);
-                }
-                return events;
-            } finally {
-                lock.writeLock().unlock();
-            }
-        }
-
-        public ImmutablePort getPort(String name) {
-            if (name == null) {
-                throw new NullPointerException("Port name must not be null");
-            }
-            lock.readLock().lock();
-            try {
-                return portsByName.get(name.toLowerCase());
-            } finally {
-                lock.readLock().unlock();
-            }
-        }
-
-        public ImmutablePort getPort(Short portNumber) {
-            lock.readLock().lock();
-            try {
-                return portsByNumber.get(portNumber);
-            } finally {
-                lock.readLock().unlock();
-            }
-        }
-
-        public List<ImmutablePort> getPorts() {
-            lock.readLock().lock();
-            try {
-                return portList;
-            } finally {
-                lock.readLock().unlock();
-            }
-        }
-
-        public List<ImmutablePort> getEnabledPorts() {
-            lock.readLock().lock();
-            try {
-                return enabledPortList;
-            } finally {
-                lock.readLock().unlock();
-            }
-        }
-
-        public List<Short> getEnabledPortNumbers() {
-            lock.readLock().lock();
-            try {
-                return enabledPortNumbers;
-            } finally {
-                lock.readLock().unlock();
-            }
-        }
-    }
-
-
-    @Override
-    public boolean attributeEquals(String name, Object other) {
-        Object attr = this.attributes.get(name);
-        if (attr == null)
-            return false;
-        return attr.equals(other);
-    }
-
-
-    @Override
-    public Object getAttribute(String name) {
-        // returns null if key doesn't exist
-        return this.attributes.get(name);
-    }
-
-    @Override
-    public void setAttribute(String name, Object value) {
-        this.attributes.put(name, value);
-        return;
-    }
-
-    @Override
-    public Object removeAttribute(String name) {
-        return this.attributes.remove(name);
-    }
-
-    @Override
-    public boolean hasAttribute(String name) {
-        return this.attributes.containsKey(name);
-    }
-
-    @Override
-    @JsonIgnore
-    public void setChannel(Channel channel) {
-        this.channel = channel;
-    }
-
-    // For driver subclass to set throttling
-    protected void enableWriteThrottle(boolean enable) {
-        this.writeThrottleEnabled = enable;
-    }
-
-    @Override
-    public boolean isWriteThrottleEnabled() {
-        return this.writeThrottleEnabled;
-    }
-
-    @Override
-    @LogMessageDocs({
-        @LogMessageDoc(level="WARN",
-                message="Drop throttled OF message to switch {switch}",
-                explanation="The controller is sending more messages" +
-                "than the switch can handle. Some messages are dropped" +
-                "to prevent switch outage",
-                recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
-    })
-    public void writeThrottled(OFMessage m, FloodlightContext bc)
-            throws IOException {
-        if (channel == null || !isConnected())
-            return;
-        /**
-         * By default, channel uses an unbounded send queue. Enable throttling
-         * prevents the queue from growing big.
-         *
-         * channel.isWritable() returns true when queue length is less than
-         * high water mark (64 kbytes). Once exceeded, isWritable() becomes
-         * false after queue length drops below low water mark (32 kbytes).
-         */
-        if (!writeThrottleEnabled || channel.isWritable()) {
-            write(m, bc);
-        } else {
-            // Let logback duplicate filtering take care of excessive logs
-            ctrSwitchWriteDrops.updateCounterNoFlush();
-            log.warn("Drop throttled OF message to switch {}", this);
-        }
-    }
-
-    @Override
-    public void writeThrottled(List<OFMessage> msglist, FloodlightContext bc)
-            throws IOException {
-        if (!writeThrottleEnabled || channel.isWritable()) {
-            write(msglist, bc);
-        } else {
-            // Let logback duplicate filtering take care of excessive logs
-            ctrSwitchWriteDrops.updateCounterNoFlush(msglist.size());
-            log.warn("Drop throttled OF messages to switch {}", this);
-        }
-    }
-
-    @Override
-    public void write(OFMessage m, FloodlightContext bc) {
-        if (channel == null || !isConnected())
-            return;
-            //throws IOException {
-        Map<IOFSwitch,List<OFMessage>> msg_buffer_map = local_msg_buffer.get();
-        List<OFMessage> msg_buffer = msg_buffer_map.get(this);
-        if (msg_buffer == null) {
-            msg_buffer = new ArrayList<OFMessage>();
-            msg_buffer_map.put(this, msg_buffer);
-        }
-
-        this.floodlightProvider.handleOutgoingMessage(this, m, bc);
-        msg_buffer.add(m);
-
-        if ((msg_buffer.size() >= Controller.BATCH_MAX_SIZE) ||
-            ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) {
-            this.write(msg_buffer);
-            msg_buffer.clear();
-        }
-    }
-    @Override
-    @LogMessageDoc(level="WARN",
-                   message="Sending OF message that modifies switch " +
-                           "state while in the slave role: {switch}",
-                   explanation="An application has sent a message to a switch " +
-                           "that is not valid when the switch is in a slave role",
-                   recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
-    public void write(List<OFMessage> msglist,
-                      FloodlightContext bc) {
-        if (channel == null || !isConnected())
-            return;
-        for (OFMessage m : msglist) {
-            if (role == Role.SLAVE) {
-                switch (m.getType()) {
-                    case PACKET_OUT:
-                    case FLOW_MOD:
-                    case PORT_MOD:
-                        log.warn("Sending OF message that modifies switch " +
-                                 "state while in the slave role: {}",
-                                 m.getType().name());
-                        break;
-                    default:
-                        break;
-                }
-            }
-            this.floodlightProvider.handleOutgoingMessage(this, m, bc);
-        }
-        this.write(msglist);
-    }
-
-    /**
-     * Not callable by writers, but allow IOFSwitch implementation to override
-     * @param msglist
-     * @throws IOException
-     */
-    protected void write(List<OFMessage> msglist) {
-        if (channel == null || !isConnected())
-            return;
-        this.channel.write(msglist);
-    }
-
-    @Override
-    public void disconnectOutputStream() {
-        if (channel == null)
-            return;
-        channel.close();
-    }
-
-    @Override
-    @JsonIgnore
-    public void setFeaturesReply(OFFeaturesReply featuresReply) {
-        if (stringId == null) {
-            /* ports are updated via port status message, so we
-             * only fill in ports on initial connection.
-             */
-            List<ImmutablePort> immutablePorts = ImmutablePort
-                    .immutablePortListOf(featuresReply.getPorts());
-            portManager.updatePorts(immutablePorts);
-        }
-        this.datapathId = featuresReply.getDatapathId();
-        this.stringId = HexString.toHexString(featuresReply.getDatapathId());
-        this.capabilities = featuresReply.getCapabilities();
-        this.buffers = featuresReply.getBuffers();
-        this.actions = featuresReply.getActions();
-        this.tables = featuresReply.getTables();
-}
-
-    @Override
-    @JsonIgnore
-    public Collection<ImmutablePort> getEnabledPorts() {
-        return portManager.getEnabledPorts();
-    }
-
-    @Override
-    @JsonIgnore
-    public Collection<Short> getEnabledPortNumbers() {
-        return portManager.getEnabledPortNumbers();
-    }
-
-    @Override
-    public ImmutablePort getPort(short portNumber) {
-        return portManager.getPort(portNumber);
-    }
-
-    @Override
-    public ImmutablePort getPort(String portName) {
-        return portManager.getPort(portName);
-    }
-
-    @Override
-    @JsonIgnore
-    public OrderedCollection<PortChangeEvent>
-            processOFPortStatus(OFPortStatus ps) {
-        return portManager.handlePortStatusMessage(ps);
-    }
-
-    @Override
-    @JsonProperty("ports")
-    public Collection<ImmutablePort> getPorts() {
-        return portManager.getPorts();
-    }
-
-    @Override
-    public OrderedCollection<PortChangeEvent>
-            comparePorts(Collection<ImmutablePort> ports) {
-        return portManager.comparePorts(ports);
-    }
-
-    @Override
-    @JsonIgnore
-    public OrderedCollection<PortChangeEvent>
-            setPorts(Collection<ImmutablePort> ports) {
-        return portManager.updatePorts(ports);
-    }
-
-    @Override
-    public boolean portEnabled(short portNumber) {
-        ImmutablePort p = portManager.getPort(portNumber);
-        if (p == null) return false;
-        return p.isEnabled();
-    }
-
-    @Override
-    public boolean portEnabled(String portName) {
-        ImmutablePort p = portManager.getPort(portName);
-        if (p == null) return false;
-        return p.isEnabled();
-    }
-
-    @Override
-    @JsonSerialize(using=DPIDSerializer.class)
-    @JsonProperty("dpid")
-    public long getId() {
-        if (this.stringId == null)
-            throw new RuntimeException("Features reply has not yet been set");
-        return this.datapathId;
-    }
-
-    @JsonIgnore
-    @Override
-    public String getStringId() {
-        return stringId;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        String channelString =
-                (channel != null) ? channel.getRemoteAddress().toString() :
-                                    "?";
-        return "OFSwitchBase [" + channelString + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
-    }
-
-    @Override
-    public ConcurrentMap<Object, Object> getAttributes() {
-        return this.attributes;
-    }
-
-    @Override
-    public Date getConnectedSince() {
-        return connectedSince;
-    }
-
-    @JsonIgnore
-    @Override
-    public int getNextTransactionId() {
-        return this.transactionIdSource.incrementAndGet();
-    }
-
-    @Override
-    public void sendStatsQuery(OFStatisticsRequest request, int xid,
-                                IOFMessageListener caller) throws IOException {
-        request.setXid(xid);
-        this.iofMsgListenersMap.put(xid, caller);
-        List<OFMessage> msglist = new ArrayList<OFMessage>(1);
-        msglist.add(request);
-        this.write(msglist);
-        return;
-    }
-
-    @Override
-    public Future<List<OFStatistics>> queryStatistics(OFStatisticsRequest request) throws IOException {
-        request.setXid(getNextTransactionId());
-        OFStatisticsFuture future = new OFStatisticsFuture(threadPool, this, request.getXid());
-        this.statsFutureMap.put(request.getXid(), future);
-        List<OFMessage> msglist = new ArrayList<OFMessage>(1);
-        msglist.add(request);
-        this.write(msglist);
-        return future;
-    }
-
-    @Override
-    public void deliverStatisticsReply(OFStatisticsReply reply) {
-        checkForTableStats(reply);
-        OFStatisticsFuture future = this.statsFutureMap.get(reply.getXid());
-        if (future != null) {
-            future.deliverFuture(this, reply);
-            // The future will ultimately unregister itself and call
-            // cancelStatisticsReply
-            return;
-        }
-        /* Transaction id was not found in statsFutureMap.check the other map */
-        IOFMessageListener caller = this.iofMsgListenersMap.get(reply.getXid());
-        if (caller != null) {
-            caller.receive(this, reply, null);
-        }
-    }
-
-    @LogMessageDocs({
-        @LogMessageDoc(level="INFO",
-            message="Switch {switch} flow table is full",
-            explanation="The switch flow table at least 98% full, " +
-                    "this requires attention if using reactive flow setup"),
-        @LogMessageDoc(level="INFO",
-            message="Switch {switch} flow table capacity back to normal",
-            explanation="The switch flow table is less than 90% full")
-    })
-    private void checkForTableStats(OFStatisticsReply statReply) {
-        if (statReply.getStatisticType() != OFStatisticsType.TABLE) {
-            return;
-        }
-        List<? extends OFStatistics> stats = statReply.getStatistics();
-        // Assume a single table only
-        OFStatistics stat = stats.get(0);
-        if (stat instanceof OFTableStatistics) {
-            OFTableStatistics tableStat = (OFTableStatistics) stat;
-            int activeCount = tableStat.getActiveCount();
-            int maxEntry = tableStat.getMaximumEntries();
-            log.debug("Switch {} active entries {} max entries {}",
-                    new Object[] { this.stringId, activeCount, maxEntry});
-            int percentFull = activeCount * 100 / maxEntry;
-            if (flowTableFull && percentFull < 90) {
-                log.info("Switch {} flow table capacity is back to normal",
-                        toString());
-                floodlightProvider.addSwitchEvent(this.datapathId,
-                        "SWITCH_FLOW_TABLE_NORMAL < 90% full", false);
-            } else if (percentFull >= 98) {
-                log.info("Switch {} flow table is almost full", toString());
-                floodlightProvider.addSwitchEvent(this.datapathId,
-                        "SWITCH_FLOW_TABLE_ALMOST_FULL >= 98% full", false);
-            }
-        }
-    }
-
-
-    @Override
-    public void cancelStatisticsReply(int transactionId) {
-        if (null ==  this.statsFutureMap.remove(transactionId)) {
-            this.iofMsgListenersMap.remove(transactionId);
-        }
-    }
-
-    @Override
-    public void cancelAllStatisticsReplies() {
-        /* we don't need to be synchronized here. Even if another thread
-         * modifies the map while we're cleaning up the future will eventuall
-         * timeout */
-        for (OFStatisticsFuture f : statsFutureMap.values()) {
-            f.cancel(true);
-        }
-        statsFutureMap.clear();
-        iofMsgListenersMap.clear();
-    }
-
-
-    /**
-     * @param floodlightProvider the floodlightProvider to set
-     */
-    @JsonIgnore
-    public void setFloodlightProvider(
-            IFloodlightProviderService floodlightProvider) {
-        this.floodlightProvider = floodlightProvider;
-    }
-
-    @Override
-    @JsonIgnore
-    public void setThreadPoolService(IThreadPoolService tp) {
-        this.threadPool = tp;
-    }
-
-    @Override
-    @JsonIgnore
-    public void setDebugCounterService(IDebugCounterService debugCounters)
-            throws CounterException {
-        this.debugCounters = debugCounters;
-        registerOverloadCounters();
-    }
-
-    @JsonIgnore
-    @Override
-    public boolean isConnected() {
-        // no lock needed since we use volatile
-        return connected;
-    }
-
-    @JsonIgnore
-    @Override
-    public boolean isActive() {
-        // no lock needed since we use volatile
-        return isConnected() && this.role == Role.MASTER;
-    }
-
-    @Override
-    @JsonIgnore
-    public void setConnected(boolean connected) {
-        // No lock needed since we use volatile
-        if (connected && this.connectedSince == null)
-            this.connectedSince = new Date();
-        else if (!connected)
-            this.connectedSince = null;
-        this.connected = connected;
-    }
-
-    @Override
-    public Role getHARole() {
-        return role;
-    }
-
-    @JsonIgnore
-    @Override
-    public void setHARole(Role role) {
-        this.role = role;
-    }
-
-    @LogMessageDoc(level="INFO",
-            message="Switch {switch} flow cleared",
-            explanation="The switch flow table has been cleared, " +
-                    "this normally happens on switch connection")
-    @Override
-    public void clearAllFlowMods() {
-        if (channel == null || !isConnected())
-            return;
-        // Delete all pre-existing flows
-        log.info("Clearing all flows on switch {}", this);
-        OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL);
-        OFMessage fm = ((OFFlowMod) floodlightProvider.getOFMessageFactory()
-            .getMessage(OFType.FLOW_MOD))
-                .setMatch(match)
-            .setCommand(OFFlowMod.OFPFC_DELETE)
-            .setOutPort(OFPort.OFPP_NONE)
-            .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH));
-        fm.setXid(getNextTransactionId());
-        OFMessage barrierMsg = floodlightProvider.getOFMessageFactory().getMessage(
-                OFType.BARRIER_REQUEST);
-        barrierMsg.setXid(getNextTransactionId());
-        List<OFMessage> msglist = new ArrayList<OFMessage>(2);
-        msglist.add(fm);
-        msglist.add(barrierMsg);
-        channel.write(msglist);
-    }
-
-    @Override
-    public boolean updateBroadcastCache(Long entry, Short port) {
-        if (timedCache.update(entry)) {
-            AtomicLong count = portBroadcastCacheHitMap.get(port);
-            if(count == null) {
-                AtomicLong newCount = new AtomicLong(0);
-                AtomicLong retrieved;
-                if((retrieved = portBroadcastCacheHitMap.putIfAbsent(port, newCount)) == null ) {
-                    count = newCount;
-                } else {
-                    count = retrieved;
-                }
-            }
-            count.incrementAndGet();
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    @JsonIgnore
-    public Map<Short, Long> getPortBroadcastHits() {
-        Map<Short, Long> res = new HashMap<Short, Long>();
-        for (Map.Entry<Short, AtomicLong> entry : portBroadcastCacheHitMap.entrySet()) {
-            res.put(entry.getKey(), entry.getValue().get());
-        }
-        return res;
-    }
-
-    @Override
-    public void flush() {
-        Map<IOFSwitch,List<OFMessage>> msg_buffer_map = local_msg_buffer.get();
-        List<OFMessage> msglist = msg_buffer_map.get(this);
-        if ((msglist != null) && (msglist.size() > 0)) {
-            /* ============================ BIG CAVEAT ===============================
-             * This code currently works, but relies on undocumented behavior of
-             * netty.
-             *
-             * The method org.jboss.netty.channel.Channel.write(Object)
-             * (invoked from this.write(List<OFMessage> msg) is currently
-             * documented to be <emph>asynchronous</emph>. If the method /were/ truely
-             * asynchronous, this would break our code (because we are clearing the
-             * msglist right after calling write.
-             *
-             * For now, Netty actually invokes the conversion pipeline before doing
-             * anything asynchronous, so we are safe. But we should probably change
-             * that behavior.
-             */
-            this.write(msglist);
-            msglist.clear();
-        }
-    }
-
-    public static void flush_all() {
-        Map<IOFSwitch,List<OFMessage>> msg_buffer_map = local_msg_buffer.get();
-        for (IOFSwitch sw : msg_buffer_map.keySet()) {
-            sw.flush();
-        }
-    }
-
-
-    /**
-     * Get the IP Address for the switch
-     * @return the inet address
-     */
-    @Override
-    @JsonSerialize(using=ToStringSerializer.class)
-    public SocketAddress getInetAddress() {
-        if (channel == null)
-            return null;
-        return channel.getRemoteAddress();
-    }
-
-    @Override
-    public Future<OFFeaturesReply> querySwitchFeaturesReply()
-            throws IOException {
-        OFMessage request =
-                floodlightProvider.getOFMessageFactory().
-                    getMessage(OFType.FEATURES_REQUEST);
-        request.setXid(getNextTransactionId());
-        OFFeaturesReplyFuture future =
-                new OFFeaturesReplyFuture(threadPool, this, request.getXid());
-        this.featuresFutureMap.put(request.getXid(), future);
-        List<OFMessage> msglist = new ArrayList<OFMessage>(1);
-        msglist.add(request);
-        this.write(msglist);
-        return future;
-    }
-
-    @Override
-    public void deliverOFFeaturesReply(OFMessage reply) {
-        OFFeaturesReplyFuture future = this.featuresFutureMap.get(reply.getXid());
-        if (future != null) {
-            future.deliverFuture(this, reply);
-            // The future will ultimately unregister itself and call
-            // cancelFeaturesReply
-            return;
-        }
-        log.error("Switch {}: received unexpected featureReply", this);
-    }
-
-    @Override
-    public void cancelFeaturesReply(int transactionId) {
-        this.featuresFutureMap.remove(transactionId);
-    }
-
-
-    @Override
-    public int getBuffers() {
-        return buffers;
-    }
-
-
-    @Override
-    public int getActions() {
-        return actions;
-    }
-
-
-    @Override
-    public int getCapabilities() {
-        return capabilities;
-    }
-
-
-    @Override
-    public byte getTables() {
-        return tables;
-    }
-
-    @Override
-    public OFDescriptionStatistics getDescriptionStatistics() {
-        return new OFDescriptionStatistics(description);
-    }
-
-
-    @Override
-    public void setFloodlightProvider(Controller controller) {
-        floodlightProvider = controller;
-    }
-
-
-    /**
-     * For switch drivers to set thresholds, all rates in per second
-     * @param pktInHigh - above this start throttling
-     * @param pktInLow  - below this stop throttling
-     * @param pktInPerMac  - block host if unique pktIn rate reaches this
-     * @param pktInPerPort - block port if unique pktIn rate reaches this
-     */
-    @JsonIgnore
-    protected void setInputThrottleThresholds(int pktInHigh, int pktInLow,
-            int pktInPerMac, int pktInPerPort) {
-        packetInRateThresholdHigh = pktInHigh;
-        packetInRateThresholdLow = pktInLow;
-        packetInRatePerMacThreshold = pktInPerMac;
-        packetInRatePerPortThreshold = pktInPerPort;
-    }
-
-    /**
-     * Return if switch has exceeded the high threshold of packet in rate.
-     * @return
-     */
-    @Override
-    public boolean isOverloaded() {
-        return packetInThrottleEnabled;
-    }
-
-    /**
-     * Determine if this message should be dropped.
-     *
-     * We compute the current rate by taking a timestamp every 100 messages.
-     * Could change to a more complex scheme if more accuracy is needed.
-     *
-     * Enable throttling if the rate goes above packetInRateThresholdHigh
-     * Disable throttling when the rate drops below packetInRateThresholdLow
-     *
-     * While throttling is enabled, we do the following:
-     *  - Remove duplicate packetIn's mapped to the same OFMatch
-     *  - After filtering, if packetIn rate per host (mac) is above
-     *    packetInRatePerMacThreshold, push a flow mod to block mac on port
-     *  - After filtering, if packetIn rate per port is above
-     *    packetInRatePerPortThreshold, push a flow mod to block port
-     *  - Allow blocking flow mods have a hard timeout and expires automatically
-     *
-     * TODO: keep a history of all events related in input throttling
-     *
-     * @param ofm
-     * @return
-     */
-    @Override
-    public boolean inputThrottled(OFMessage ofm) {
-        if (ofm.getType() != OFType.PACKET_IN) {
-            return false;
-        }
-        ctrSwitchPktin.updateCounterNoFlush();
-        // Compute current packet in rate
-        messageCount++;
-        if (messageCount % 1000 == 0) {
-            long now = System.currentTimeMillis();
-            if (now != lastMessageTime) {
-                currentRate = (int) (1000000 / (now - lastMessageTime));
-                lastMessageTime = now;
-            } else {
-                currentRate = Integer.MAX_VALUE;
-            }
-        }
-        if (!packetInThrottleEnabled) {
-            if (currentRate <= packetInRateThresholdHigh) {
-                return false; // most common case
-            }
-            enablePacketInThrottle();
-        } else if (currentRate < packetInRateThresholdLow) {
-            disablePacketInThrottle();
-            return false;
-        }
-
-        // Now we are in the slow path where we need to do filtering
-        // First filter based on OFMatch
-        OFPacketIn pin = (OFPacketIn)ofm;
-        OFMatch match = new OFMatch();
-        match.loadFromPacket(pin.getPacketData(), pin.getInPort());
-        if (ofMatchCache.update(match)) {
-           ctrSwitchPktinDrops.updateCounterNoFlush();
-            return true;
-        }
-
-        // We have packet in with a distinct flow, check per mac rate
-        messageCountUniqueOFMatch++;
-        if ((messageCountUniqueOFMatch % packetInRatePerMacThreshold) == 1) {
-            checkPerSourceMacRate(pin);
-        }
-
-        // Check per port rate
-        if ((messageCountUniqueOFMatch % packetInRatePerPortThreshold) == 1) {
-            checkPerPortRate(pin);
-        }
-        return false;
-    }
-
-    /**
-     * We rely on the fact that packet in processing is single threaded
-     * per packet-in, so no locking is necessary.
-     */
-    private void disablePacketInThrottle() {
-        ofMatchCache = null;
-        macCache = null;
-        macBlockedCache = null;
-        portCache = null;
-        portBlockedCache = null;
-        packetInThrottleEnabled = false;
-        floodlightProvider.addSwitchEvent(this.datapathId,
-                "SWITCH_OVERLOAD_THROTTLE_DISABLED ==>" +
-                "Pktin rate " + currentRate + "/s", false);
-        log.info("Packet in rate is {}, disable throttling on {}",
-                currentRate, this);
-    }
-
-    private void enablePacketInThrottle() {
-        ofMatchCache = new TimedCache<OFMatch>(2048, 5000); // 5 second interval
-        macCache = new TimedCache<Long>(64, 1000 );  // remember last second
-        macBlockedCache = new TimedCache<Long>(256, 5000 );  // 5 second interval
-        portCache = new TimedCache<Short>(16, 1000 );  // rememeber last second
-        portBlockedCache = new TimedCache<Short>(64, 5000 );  // 5 second interval
-        packetInThrottleEnabled = true;
-        messageCountUniqueOFMatch = 0;
-        floodlightProvider.addSwitchEvent(this.datapathId,
-                "SWITCH_OVERLOAD_THROTTLE_ENABLED ==>" +
-                "Pktin rate " + currentRate + "/s", false);
-        log.info("Packet in rate is {}, enable throttling on {}",
-                currentRate, this);
-    }
-
-    private void registerOverloadCounters() throws CounterException {
-        if (debugCountersRegistered) {
-            return;
-        }
-        if (debugCounters == null) {
-            log.error("Debug Counter Service not found");
-            debugCounters = new NullDebugCounter();
-            debugCountersRegistered = true;
-        }
-        // every level of the hierarchical counter has to be registered
-        // even if they are not used
-        ctrSwitch = debugCounters.registerCounter(
-                                   PACKAGE , stringId,
-                                   "Counter for this switch",
-                                   CounterType.ALWAYS_COUNT);
-        ctrSwitchPktin = debugCounters.registerCounter(
-                                   PACKAGE, stringId + "/pktin",
-                                   "Packet in counter for this switch",
-                                   CounterType.ALWAYS_COUNT);
-        ctrSwitchWrite = debugCounters.registerCounter(
-                                   PACKAGE, stringId + "/write",
-                                   "Write counter for this switch",
-                                   CounterType.ALWAYS_COUNT);
-        ctrSwitchPktinDrops = debugCounters.registerCounter(
-                                   PACKAGE, stringId + "/pktin/drops",
-                                   "Packet in throttle drop count",
-                                   CounterType.ALWAYS_COUNT,
-                                   IDebugCounterService.CTR_MDATA_WARN);
-        ctrSwitchWriteDrops = debugCounters.registerCounter(
-                                   PACKAGE, stringId + "/write/drops",
-                                   "Switch write throttle drop count",
-                                   CounterType.ALWAYS_COUNT,
-                                   IDebugCounterService.CTR_MDATA_WARN);
-    }
-
-    /**
-     * Check if we have sampled this mac in the last second.
-     * Since we check every packetInRatePerMacThreshold packets,
-     * the presence of the mac in the macCache means the rate is
-     * above the threshold in a statistical sense.
-     *
-     * Take care not to block topology probing packets. Also don't
-     * push blocking flow mod if we have already done so within the
-     * last 5 seconds.
-     *
-     * @param pin
-     * @return
-     */
-    private void checkPerSourceMacRate(OFPacketIn pin) {
-        byte[] data = pin.getPacketData();
-        byte[] mac = Arrays.copyOfRange(data, 6, 12);
-        MACAddress srcMac = MACAddress.valueOf(mac);
-        short ethType = (short) (((data[12] & 0xff) << 8) + (data[13] & 0xff));
-        if (ethType != Ethernet.TYPE_LLDP && ethType != Ethernet.TYPE_BSN &&
-                macCache.update(srcMac.toLong())) {
-            // Check if we already pushed a flow in the last 5 seconds
-            if (macBlockedCache.update(srcMac.toLong())) {
-                return;
-            }
-            // write out drop flow per srcMac
-            int port = pin.getInPort();
-            SwitchPort swPort = new SwitchPort(getId(), port);
-            ForwardingBase.blockHost(floodlightProvider,
-                    swPort, srcMac.toLong(), (short) 5,
-                    AppCookie.makeCookie(OFSWITCH_APP_ID, 0));
-            floodlightProvider.addSwitchEvent(this.datapathId,
-                    "SWITCH_PORT_BLOCKED_TEMPORARILY " +
-                    "OFPort " + port + " mac " + srcMac, false);
-            log.info("Excessive packet in from {} on {}, block host for 5 sec",
-                    srcMac.toString(), swPort);
-        }
-    }
-
-    /**
-     * Works in a similar way as checkPerSourceMacRate().
-     *
-     * TODO Don't block ports with links?
-     *
-     * @param pin
-     * @return
-     */
-    private void checkPerPortRate(OFPacketIn pin) {
-        Short port = pin.getInPort();
-        if (portCache.update(port)) {
-            // Check if we already pushed a flow in the last 5 seconds
-            if (portBlockedCache.update(port)) {
-                return;
-            }
-            // write out drop flow per port
-            SwitchPort swPort = new SwitchPort(getId(), port);
-            ForwardingBase.blockHost(floodlightProvider,
-                    swPort, -1L, (short) 5,
-                    AppCookie.makeCookie(OFSWITCH_APP_ID, 1));
-            floodlightProvider.addSwitchEvent(this.datapathId,
-                    "SWITCH_PORT_BLOCKED_TEMPORARILY " +
-                    "OFPort " + port, false);
-            log.info("Excessive packet in from {}, block port for 5 sec",
-                    swPort);
-        }
-    }
-
-    @Override
-    @JsonIgnore
-    @LogMessageDoc(level="WARN",
-        message="Switch {switch} flow table is full",
-        explanation="The controller received flow table full " +
-                "message from the switch, could be caused by increased " +
-                "traffic pattern",
-                recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
-    public void setTableFull(boolean isFull) {
-        if (isFull && !flowTableFull) {
-            floodlightProvider.addSwitchEvent(this.datapathId,
-                    "SWITCH_FLOW_TABLE_FULL " +
-                    "Table full error from switch", false);
-            log.warn("Switch {} flow table is full", stringId);
-        }
-        flowTableFull = isFull;
-    }
-
-
-    @Override
-    public short getAccessFlowPriority() {
-        return accessFlowPriority;
-    }
-
-
-    @Override
-    public short getCoreFlowPriority() {
-        return coreFlowPriority;
-    }
-
-
-    @Override
-    public void setAccessFlowPriority(short accessFlowPriority) {
-        this.accessFlowPriority = accessFlowPriority;
-    }
-
-
-    @Override
-    public void setCoreFlowPriority(short coreFlowPriority) {
-        this.coreFlowPriority = coreFlowPriority;
-    }
-
-    @Override
-    public void startDriverHandshake() {
-        if (startDriverHandshakeCalled)
-            throw new SwitchDriverSubHandshakeAlreadyStarted();
-        startDriverHandshakeCalled = true;
-    }
-
-    @Override
-    public boolean isDriverHandshakeComplete() {
-        if (!startDriverHandshakeCalled)
-            throw new SwitchDriverSubHandshakeNotStarted();
-        return true;
-    }
-
-    @Override
-    public void processDriverHandshakeMessage(OFMessage m) {
-        if (startDriverHandshakeCalled)
-            throw new SwitchDriverSubHandshakeCompleted(m);
-        else
-            throw new SwitchDriverSubHandshakeNotStarted();
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/PortChangeEvent.java b/src/main/java/net/floodlightcontroller/core/PortChangeEvent.java
new file mode 100644
index 000000000..cca90d3a3
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/PortChangeEvent.java
@@ -0,0 +1,54 @@
+package net.floodlightcontroller.core;
+
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+
+
+/**
+ * Describes a change of an open flow port
+ */
+public class PortChangeEvent {
+    public final OFPortDesc port;
+    public final PortChangeType type;
+    /**
+     * @param port
+     * @param type
+     */
+    public PortChangeEvent(OFPortDesc port,
+                           PortChangeType type) {
+        this.port = port;
+        this.type = type;
+    }
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((port == null) ? 0 : port.hashCode());
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        return result;
+    }
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        PortChangeEvent other = (PortChangeEvent) obj;
+        if (port == null) {
+            if (other.port != null) return false;
+        } else if (!port.equals(other.port)) return false;
+        if (type != other.type) return false;
+        return true;
+    }
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "[" + type + " " + String.format("%s (%d)", port.getName(), port.getPortNo()) + "]";
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/PortChangeType.java b/src/main/java/net/floodlightcontroller/core/PortChangeType.java
new file mode 100644
index 000000000..178d27b76
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/PortChangeType.java
@@ -0,0 +1,8 @@
+package net.floodlightcontroller.core;
+
+/**
+ * the type of change that happened to an open flow port
+ */
+public enum PortChangeType {
+    ADD, OTHER_UPDATE, DELETE, UP, DOWN,
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/RoleInfo.java b/src/main/java/net/floodlightcontroller/core/RoleInfo.java
index 1e6c186f7..31ec6464c 100644
--- a/src/main/java/net/floodlightcontroller/core/RoleInfo.java
+++ b/src/main/java/net/floodlightcontroller/core/RoleInfo.java
@@ -16,67 +16,34 @@
 
 package net.floodlightcontroller.core;
 
-import java.text.SimpleDateFormat;
 import java.util.Date;
-import java.util.TimeZone;
-
-import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 
 
 public class RoleInfo {
-    protected String role;
-    protected String roleChangeDescription;
-    protected Date roleChangeDateTime;
-
-    public RoleInfo() {
-    }
-
-    public RoleInfo(RoleInfo o) {
-        role = o.role;
-        roleChangeDescription = o.roleChangeDescription;
-        roleChangeDateTime = (Date)o.roleChangeDateTime.clone();
-    }
+    private final HARole role;
+    private final String roleChangeDescription;
+    private final Date roleChangeDateTime;
 
-    public RoleInfo(String role) {
-        setRole(role);
-    }
-
-    public RoleInfo(Role role, String description) {
-        this.role = (role != null) ? role.name() : "DISABLED";
-        this.roleChangeDescription = description;
-    }
-
-    public RoleInfo(Role role, String description, Date dt) {
-        this.role = (role != null) ? role.name() : "DISABLED";
+    public RoleInfo(HARole role, String description, Date dt) {
+        this.role = role;
         this.roleChangeDescription = description;
         this.roleChangeDateTime = dt;
     }
 
-    public String getRole() {
+    public HARole getRole() {
         return role;
     }
 
-    public void setRole(String role) {
-        this.role = role;
-    }
-
     @JsonProperty(value="change-description")
     public String getRoleChangeDescription() {
         return roleChangeDescription;
     }
-    @JsonProperty(value="change-description")
-    public void setRoleChangeDescription(String roleChangeDescription) {
-        this.roleChangeDescription = roleChangeDescription;
-    }
+
     @JsonProperty(value="change-date-time")
-    public String getRoleChangeDateTime() {
-        SimpleDateFormat formatter =
-                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
-        formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
-        return roleChangeDateTime == null ?
-                  "" : formatter.format(roleChangeDateTime);
+    public Date getRoleChangeDateTime() {
+        return roleChangeDateTime;
     }
 
-}
\ No newline at end of file
+}
diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDescription.java b/src/main/java/net/floodlightcontroller/core/SwitchDescription.java
new file mode 100644
index 000000000..57697d709
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/SwitchDescription.java
@@ -0,0 +1,182 @@
+package net.floodlightcontroller.core;
+
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+
+/**
+ * Encapsulates the switch information return from the description stats request
+ *
+ * @author Rob Vaterlaus <rob.vaterlaus@bigswitch.com>
+ */
+public class SwitchDescription {
+
+    public static class Builder {
+
+        private String manufacturerDescription;
+        private String hardwareDescription;
+        private String softwareDescription;
+        private String serialNumber;
+        private String datapathDescription;
+
+        public Builder() {
+            manufacturerDescription = "";
+            hardwareDescription = "";
+            softwareDescription = "";
+            serialNumber = "";
+            datapathDescription = "";
+        }
+
+        public Builder setManufacturerDescription(String manufacturerDescription) {
+            this.manufacturerDescription = manufacturerDescription;
+            return this;
+        }
+
+        public Builder setHardwareDescription(String hardwareDescription) {
+            this.hardwareDescription = hardwareDescription;
+            return this;
+        }
+
+        public Builder setSoftwareDescription(String softwareDescription) {
+            this.softwareDescription = softwareDescription;
+            return this;
+        }
+
+        public Builder setSerialNumber(String serialNumber) {
+            this.serialNumber = serialNumber;
+            return this;
+        }
+
+        public Builder setDatapathDescription(String datapathDescription) {
+            this.datapathDescription = datapathDescription;
+            return this;
+        }
+
+        public SwitchDescription build() {
+            return new SwitchDescription(manufacturerDescription,
+                    hardwareDescription, softwareDescription, serialNumber,
+                    datapathDescription);
+        }
+    }
+
+    private final String manufacturerDescription;
+    private final String hardwareDescription;
+    private final String softwareDescription;
+    private final String serialNumber;
+    private final String datapathDescription;
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    // FIXME: Should make this private
+    public SwitchDescription() {
+        this("", "", "", "", "");
+    }
+
+    // FIXME: Should make this private
+    public SwitchDescription(String manufacturerDescription,
+            String hardwareDescription, String softwareDescription,
+            String serialNumber, String datapathDescription) {
+        this.manufacturerDescription = manufacturerDescription;
+        this.hardwareDescription = hardwareDescription;
+        this.softwareDescription = softwareDescription;
+        this.serialNumber = serialNumber;
+        this.datapathDescription = datapathDescription;
+    }
+
+    public SwitchDescription(OFDescStatsReply descStatsReply) {
+        this(descStatsReply.getMfrDesc(), descStatsReply.getHwDesc(),
+                descStatsReply.getSwDesc(), descStatsReply.getSerialNum(),
+                descStatsReply.getDpDesc());
+    }
+
+    public String getManufacturerDescription() {
+        return manufacturerDescription;
+    }
+
+    public String getHardwareDescription() {
+        return hardwareDescription;
+    }
+
+    public String getSoftwareDescription() {
+        return softwareDescription;
+    }
+
+    public String getSerialNumber() {
+        return serialNumber;
+    }
+
+    public String getDatapathDescription() {
+        return datapathDescription;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime
+                * result
+                + ((datapathDescription == null) ? 0 : datapathDescription
+                        .hashCode());
+        result = prime
+                * result
+                + ((hardwareDescription == null) ? 0 : hardwareDescription
+                        .hashCode());
+        result = prime
+                * result
+                + ((manufacturerDescription == null) ? 0
+                        : manufacturerDescription.hashCode());
+        result = prime * result
+                + ((serialNumber == null) ? 0 : serialNumber.hashCode());
+        result = prime
+                * result
+                + ((softwareDescription == null) ? 0 : softwareDescription
+                        .hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        SwitchDescription other = (SwitchDescription) obj;
+        if (datapathDescription == null) {
+            if (other.datapathDescription != null)
+                return false;
+        } else if (!datapathDescription.equals(other.datapathDescription))
+            return false;
+        if (hardwareDescription == null) {
+            if (other.hardwareDescription != null)
+                return false;
+        } else if (!hardwareDescription.equals(other.hardwareDescription))
+            return false;
+        if (manufacturerDescription == null) {
+            if (other.manufacturerDescription != null)
+                return false;
+        } else if (!manufacturerDescription
+                .equals(other.manufacturerDescription))
+            return false;
+        if (serialNumber == null) {
+            if (other.serialNumber != null)
+                return false;
+        } else if (!serialNumber.equals(other.serialNumber))
+            return false;
+        if (softwareDescription == null) {
+            if (other.softwareDescription != null)
+                return false;
+        } else if (!softwareDescription.equals(other.softwareDescription))
+            return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return "SwitchDescription [manufacturerDescription=" + manufacturerDescription
+                + ", hardwareDescription=" + hardwareDescription + ", softwareDescription="
+                + softwareDescription + ", serialNumber=" + serialNumber
+                + ", datapathDescription=" + datapathDescription + "]";
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDisconnectedException.java b/src/main/java/net/floodlightcontroller/core/SwitchDisconnectedException.java
new file mode 100644
index 000000000..21b74ec74
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/SwitchDisconnectedException.java
@@ -0,0 +1,23 @@
+package net.floodlightcontroller.core;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+
+public class SwitchDisconnectedException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    private final DatapathId id;
+
+    public SwitchDisconnectedException(DatapathId id) {
+        super(genMessage(id));
+        this.id = id;
+    }
+
+    private static String genMessage(DatapathId id) {
+        return String.format("Switch %s disconnected", id);
+    }
+
+    public DatapathId getId() {
+        return id;
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeAlreadyStarted.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeAlreadyStarted.java
deleted file mode 100644
index eb5541bf9..000000000
--- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeAlreadyStarted.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package net.floodlightcontroller.core;
-
-/**
- * Thrown when IOFSwitch.startDriverHandshake() is called more than once.
- * @author gregor
- *
- */
-public class SwitchDriverSubHandshakeAlreadyStarted extends
-    SwitchDriverSubHandshakeException {
-    private static final long serialVersionUID = -5491845708752443501L;
-
-    public SwitchDriverSubHandshakeAlreadyStarted() {
-        super();
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeCompleted.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeCompleted.java
deleted file mode 100644
index ed39b5f44..000000000
--- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeCompleted.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package net.floodlightcontroller.core;
-
-import org.openflow.protocol.OFMessage;
-
-/**
- * Indicates that a message was passed to a switch driver's subhandshake
- * handling code but the driver has already completed the sub-handshake
- * @author gregor
- *
- */
-public class SwitchDriverSubHandshakeCompleted
-        extends SwitchDriverSubHandshakeException {
-    private static final long serialVersionUID = -8817822245846375995L;
-
-    public SwitchDriverSubHandshakeCompleted(OFMessage m) {
-        super("Sub-Handshake is already complete but received message " +
-              m.getType());
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeException.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeException.java
deleted file mode 100644
index 0c0c87390..000000000
--- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package net.floodlightcontroller.core;
-
-/**
- * Base class for exception thrown by switch driver sub-handshake processing
- * @author gregor
- *
- */
-public class SwitchDriverSubHandshakeException extends RuntimeException {
-    private static final long serialVersionUID = -6257836781419604438L;
-
-    protected SwitchDriverSubHandshakeException() {
-        super();
-    }
-
-    protected SwitchDriverSubHandshakeException(String arg0, Throwable arg1) {
-        super(arg0, arg1);
-    }
-
-    protected SwitchDriverSubHandshakeException(String arg0) {
-        super(arg0);
-    }
-
-    protected SwitchDriverSubHandshakeException(Throwable arg0) {
-        super(arg0);
-    }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeNotStarted.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeNotStarted.java
deleted file mode 100644
index 67ec68be2..000000000
--- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeNotStarted.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package net.floodlightcontroller.core;
-
-/**
- * Thrown when a switch driver's sub-handshake has not been started but an
- * operation requiring the sub-handshake has been attempted.
- * @author gregor
- *
- */
-public class SwitchDriverSubHandshakeNotStarted extends
-    SwitchDriverSubHandshakeException {
-    private static final long serialVersionUID = -5491845708752443501L;
-
-    public SwitchDriverSubHandshakeNotStarted() {
-        super();
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeStateException.java b/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeStateException.java
deleted file mode 100644
index 1f49aea7a..000000000
--- a/src/main/java/net/floodlightcontroller/core/SwitchDriverSubHandshakeStateException.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package net.floodlightcontroller.core;
-
-/**
- * Thrown when a switch driver's sub-handshake state-machine receives an
- * unexpected OFMessage and/or is in an invald state
- * @author gregor
- *
- */
-public class SwitchDriverSubHandshakeStateException extends
-    SwitchDriverSubHandshakeException {
-    private static final long serialVersionUID = -8249926069195147051L;
-
-    public SwitchDriverSubHandshakeStateException(String msg) {
-        super(msg);
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/SwitchSyncRepresentation.java b/src/main/java/net/floodlightcontroller/core/SwitchSyncRepresentation.java
index 6284ba3c3..ea5835108 100644
--- a/src/main/java/net/floodlightcontroller/core/SwitchSyncRepresentation.java
+++ b/src/main/java/net/floodlightcontroller/core/SwitchSyncRepresentation.java
@@ -2,16 +2,20 @@ package net.floodlightcontroller.core;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
-import net.floodlightcontroller.util.EnumBitmaps;
-import net.floodlightcontroller.util.MACAddress;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
 
-import org.openflow.protocol.OFFeaturesReply;
-import org.openflow.protocol.OFPhysicalPort;
-import org.openflow.protocol.OFPhysicalPort.OFPortState;
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
-import org.openflow.util.HexString;
+import net.floodlightcontroller.core.SwitchDescription;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.util.HexString;
+import org.projectfloodlight.openflow.protocol.OFCapabilities;
+import org.projectfloodlight.openflow.protocol.OFActionType;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -27,27 +31,11 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 public class SwitchSyncRepresentation {
     public static class SyncedPort {
         @JsonProperty
-        public short portNumber;
-        @JsonProperty
-        public long hardwareAddress;
-        @JsonProperty
-        public String name;
-        @JsonProperty
-        public int config;
-        @JsonProperty
-        public int state;
-        @JsonProperty
-        public int currentFeatures;
-        @JsonProperty
-        public int advertisedFeatures;
-        @JsonProperty
-        public int supportedFeatures;
-        @JsonProperty
-        public int peerFeatures;
+        public OFPortDesc port;
 
-        public static SyncedPort fromImmutablePort(ImmutablePort p) {
+        /*public static SyncedPort fromImmutablePort(OFPortDesc p) {
             SyncedPort rv = new SyncedPort();
-            rv.portNumber = p.getPortNumber();
+            rv.port = OFPortDesc.of(p.getPortNumber());
             if (p.getHardwareAddress() == null) {
                 rv.hardwareAddress = 0;
             } else {
@@ -66,32 +54,38 @@ public class SwitchSyncRepresentation {
                     EnumBitmaps.toBitmap(p.getSupportedFeatures());
             rv.peerFeatures = EnumBitmaps.toBitmap(p.getPeerFeatures());
             return rv;
-        }
-
-        public OFPhysicalPort toOFPhysicalPort() {
-            OFPhysicalPort p = new OFPhysicalPort();
-            p.setPortNumber(portNumber);
-            p.setHardwareAddress(MACAddress.valueOf(hardwareAddress).toBytes());
-            p.setName(name);
-            p.setConfig(config);
-            p.setState(state);
-            p.setCurrentFeatures(currentFeatures);
-            p.setAdvertisedFeatures(advertisedFeatures);
-            p.setSupportedFeatures(supportedFeatures);
-            p.setPeerFeatures(peerFeatures);
-            return p;
+        }*/
+
+        public static SyncedPort fromOFPortDesc(OFPortDesc ofpd) {
+	            SyncedPort sp = new SyncedPort();
+	            sp.port = ofpd;
+	            return sp;
+        } 
+        
+        public OFPortDesc toOFPortDesc(OFFactory factory) {
+        	OFPortDesc.Builder builder = factory.buildPortDesc();
+            builder.setPortNo(port.getPortNo());
+            builder.setHwAddr(port.getHwAddr());
+            builder.setName(port.getName());
+            builder.setConfig(port.getConfig());
+            builder.setState(port.getState());
+            builder.setCurr(port.getCurr());
+            builder.setAdvertised(port.getAdvertised());
+            builder.setSupported(port.getSupported());
+            builder.setPeer(port.getPeer());
+            return builder.build();
         }
     }
 
     // From FeaturesReply
-    private final long dpid;
-    private final int buffers;
-    private final byte tables;
-    private final int capabilities;
-    private final int actions;
+    private final DatapathId dpid;
+    private final long buffers;
+    private final short tables;
+    private final Set<OFCapabilities> capabilities;
+    private final Set<OFActionType> actions;
     private final List<SyncedPort> ports;
 
-    // From OFDescriptionStatistics
+    // From OFDescStatsReply
     private final String manufacturerDescription;
     private final String hardwareDescription;
     private final String softwareDescription;
@@ -115,11 +109,11 @@ public class SwitchSyncRepresentation {
      */
     @JsonCreator
     public SwitchSyncRepresentation(
-            @JsonProperty("dpid") long dpid,
+            @JsonProperty("dpid") DatapathId dpid,
             @JsonProperty("buffers") int buffers,
             @JsonProperty("tables") byte tables,
-            @JsonProperty("capabilities") int capabilities,
-            @JsonProperty("actions") int actions,
+            @JsonProperty("capabilities") Set<OFCapabilities> capabilities,
+            @JsonProperty("actions") Set<OFActionType> actions,
             @JsonProperty("ports") List<SyncedPort> ports,
             @JsonProperty("manufacturerDescription") String manufacturerDescription,
             @JsonProperty("hardwareDescription") String hardwareDescription,
@@ -147,7 +141,7 @@ public class SwitchSyncRepresentation {
         this.actions = sw.getActions();
         this.ports = toSyncedPortList(sw.getPorts());
 
-        OFDescriptionStatistics d = sw.getDescriptionStatistics();
+        SwitchDescription d = sw.getSwitchDescription();
         this.manufacturerDescription = d.getManufacturerDescription();
         this.hardwareDescription = d.getHardwareDescription();
         this.softwareDescription = d.getSoftwareDescription();
@@ -156,14 +150,13 @@ public class SwitchSyncRepresentation {
     }
 
     public SwitchSyncRepresentation(OFFeaturesReply fr,
-                                    OFDescriptionStatistics d) {
+                                    SwitchDescription d) {
         this.dpid = fr.getDatapathId();
-        this.buffers = fr.getBuffers();
-        this.tables = fr.getTables();
+        this.buffers = fr.getNBuffers();
+        this.tables = fr.getNTables();
         this.capabilities = fr.getCapabilities();
         this.actions = fr.getActions();
-        this.ports = toSyncedPortList(
-                ImmutablePort.immutablePortListOf(fr.getPorts()));
+        this.ports = toSyncedPortList(fr.getPorts());
 
         this.manufacturerDescription = d.getManufacturerDescription();
         this.hardwareDescription = d.getHardwareDescription();
@@ -172,65 +165,73 @@ public class SwitchSyncRepresentation {
         this.datapathDescription = d.getDatapathDescription();
     }
 
-    private static List<SyncedPort> toSyncedPortList(Collection<ImmutablePort> ports) {
+    private static List<SyncedPort> toSyncedPortList(Collection<OFPortDesc> ports) {
         List<SyncedPort> rv = new ArrayList<SyncedPort>(ports.size());
-        for (ImmutablePort p: ports) {
-            rv.add(SyncedPort.fromImmutablePort(p));
+        for (OFPortDesc p: ports) {
+            rv.add(SyncedPort.fromOFPortDesc(p));
         }
         return rv;
     }
 
-    private static List<OFPhysicalPort> toOFPhysicalPortList(Collection<SyncedPort> ports) {
-        List<OFPhysicalPort> rv = new ArrayList<OFPhysicalPort>(ports.size());
+    private static List<OFPortDesc> toOFPortDescList(OFFactory factory, Collection<SyncedPort> ports) {
+        List<OFPortDesc> rv = new ArrayList<OFPortDesc>(ports.size());
         for (SyncedPort p: ports) {
-            rv.add(p.toOFPhysicalPort());
+            rv.add(p.toOFPortDesc(factory));
         }
         return rv;
 
     }
 
     @JsonIgnore
-    public OFFeaturesReply getFeaturesReply() {
-        OFFeaturesReply fr = new OFFeaturesReply();
-        fr.setDatapathId(dpid);
-        fr.setBuffers(buffers);
-        fr.setTables(tables);
-        fr.setCapabilities(capabilities);
-        fr.setActions(actions);
-        fr.setPorts(toOFPhysicalPortList(ports));
-        return fr;
+    public OFFeaturesReply getFeaturesReply(OFFactory factory) {
+    	/**
+         * FIXME Icky work around; if a null actions got written to storage
+         * then fake up an empty one so the builder() doesn't throw
+         * a NPE.  Need to root cause why someone would write a null actions.
+         * This code will all be removed shortly -- needed to unblock BVS team.
+         */
+        Set<OFActionType> workAroundActions;
+        if (actions != null)
+            workAroundActions = actions;
+        else
+            workAroundActions = Collections.<OFActionType> emptySet();
+
+        OFFeaturesReply featuresReply = factory.buildFeaturesReply()
+                .setXid(0)
+                .setDatapathId(dpid)
+                .setNBuffers(buffers)
+                .setNTables(tables)
+                .setCapabilities(capabilities)
+                .setActions(workAroundActions)
+                .setPorts(toOFPortDescList(factory, ports))
+                .build();
+        return featuresReply;
     }
 
     @JsonIgnore
-    public OFDescriptionStatistics getDescription() {
-        OFDescriptionStatistics desc = new OFDescriptionStatistics();
-        desc.setManufacturerDescription(manufacturerDescription);
-        desc.setHardwareDescription(hardwareDescription);
-        desc.setSoftwareDescription(softwareDescription);
-        desc.setSerialNumber(serialNumber);
-        desc.setDatapathDescription(datapathDescription);
-        return desc;
+    public SwitchDescription getDescription() {
+    	return new SwitchDescription(manufacturerDescription,
+                hardwareDescription, softwareDescription, softwareDescription,
+                datapathDescription);
     }
 
-
-
-    public long getDpid() {
+    public DatapathId getDpid() {
         return dpid;
     }
 
-    public int getBuffers() {
+    public long getBuffers() {
         return buffers;
     }
 
-    public byte getTables() {
+    public short getTables() {
         return tables;
     }
 
-    public int getCapabilities() {
+    public Set<OFCapabilities> getCapabilities() {
         return capabilities;
     }
 
-    public int getActions() {
+    public Set<OFActionType> getActions() {
         return actions;
     }
 
@@ -261,7 +262,7 @@ public class SwitchSyncRepresentation {
     @Override
     public String toString() {
         String dpidString;
-        dpidString = HexString.toHexString(dpid);
+        dpidString = HexString.toHexString(dpid.getLong());
         return "SwitchSyncRepresentation [DPID=" + dpidString + "]";
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
deleted file mode 100644
index 7d6227d10..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ /dev/null
@@ -1,2696 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc.
-*    Originally created by David Erickson, Stanford University
-*
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core.internal;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.lang.management.RuntimeMXBean;
-import java.net.InetSocketAddress;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Set;
-import java.util.Stack;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.HAListenerTypeMarker;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IHAListener;
-import net.floodlightcontroller.core.IInfoProvider;
-import net.floodlightcontroller.core.IListener.Command;
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.IOFSwitch.PortChangeEvent;
-import net.floodlightcontroller.core.IOFSwitch.PortChangeType;
-import net.floodlightcontroller.core.IOFSwitchDriver;
-import net.floodlightcontroller.core.IOFSwitchListener;
-import net.floodlightcontroller.core.IReadyForReconcileListener;
-import net.floodlightcontroller.core.ImmutablePort;
-import net.floodlightcontroller.core.OFSwitchBase;
-import net.floodlightcontroller.core.RoleInfo;
-import net.floodlightcontroller.core.SwitchSyncRepresentation;
-import net.floodlightcontroller.core.annotations.LogMessageDoc;
-import net.floodlightcontroller.core.annotations.LogMessageDocs;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.util.ListenerDispatcher;
-import net.floodlightcontroller.core.web.CoreWebRoutable;
-import net.floodlightcontroller.counter.ICounterStoreService;
-import net.floodlightcontroller.debugcounter.IDebugCounter;
-import net.floodlightcontroller.debugcounter.IDebugCounterService;
-import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
-import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
-import net.floodlightcontroller.debugevent.IDebugEventService;
-import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
-import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType;
-import net.floodlightcontroller.debugevent.IEventUpdater;
-import net.floodlightcontroller.debugevent.NullDebugEvent;
-import net.floodlightcontroller.debugevent.IDebugEventService.EventType;
-import net.floodlightcontroller.debugevent.IDebugEventService.MaxEventsRegistered;
-import net.floodlightcontroller.notification.INotificationManager;
-import net.floodlightcontroller.notification.NotificationManagerFactory;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.perfmon.IPktInProcessingTimeService;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.storage.IResultSet;
-import net.floodlightcontroller.storage.IStorageSourceListener;
-import net.floodlightcontroller.storage.IStorageSourceService;
-import net.floodlightcontroller.storage.StorageException;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-import net.floodlightcontroller.util.LoadMonitor;
-import net.floodlightcontroller.util.TimedCache;
-
-import org.jboss.netty.bootstrap.ServerBootstrap;
-import org.jboss.netty.channel.ChannelPipelineFactory;
-import org.jboss.netty.channel.group.ChannelGroup;
-import org.jboss.netty.channel.group.DefaultChannelGroup;
-import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
-import org.openflow.util.HexString;
-import org.openflow.vendor.nicira.OFNiciraVendorExtensions;
-import org.sdnplatform.sync.IClosableIterator;
-import org.sdnplatform.sync.IStoreClient;
-import org.sdnplatform.sync.IStoreListener;
-import org.sdnplatform.sync.ISyncService;
-import org.sdnplatform.sync.ISyncService.Scope;
-import org.sdnplatform.sync.Versioned;
-import org.sdnplatform.sync.error.ObsoleteVersionException;
-import org.sdnplatform.sync.error.SyncException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.bigswitch.floodlight.vendor.OFVendorActions;
-
-
-
-/**
- * The main controller class.  Handles all setup and network listeners
- */
-public class Controller implements IFloodlightProviderService,
-            IStorageSourceListener, IInfoProvider {
-
-    protected static final Logger log = LoggerFactory.getLogger(Controller.class);
-    protected static final INotificationManager notifier =
-            NotificationManagerFactory.getNotificationManager(Controller.class);
-
-    static final String ERROR_DATABASE =
-            "The controller could not communicate with the system database.";
-    static final String SWITCH_SYNC_STORE_NAME =
-            Controller.class.getCanonicalName() + ".stateStore";
-
-    protected BasicFactory factory;
-    protected ConcurrentMap<OFType,
-                            ListenerDispatcher<OFType,IOFMessageListener>>
-                                messageListeners;
-
-    // OFSwitch driver binding map and order
-    private ISwitchDriverRegistry driverRegistry;
-
-    // The controllerNodeIPsCache maps Controller IDs to their IP address.
-    // It's only used by handleControllerNodeIPsChanged
-    protected HashMap<String, String> controllerNodeIPsCache;
-
-    protected Set<IOFSwitchListener> switchListeners;
-    protected ListenerDispatcher<HAListenerTypeMarker,IHAListener> haListeners;
-    protected Set<IReadyForReconcileListener> readyForReconcileListeners;
-    protected Map<String, List<IInfoProvider>> providerMap;
-    protected BlockingQueue<IUpdate> updates;
-
-    // Module dependencies
-    private IRestApiService restApi;
-    private ICounterStoreService counterStore = null;
-    private IDebugCounterService debugCounters;
-    protected IDebugEventService debugEvents;
-    private IStorageSourceService storageSource;
-    private IPktInProcessingTimeService pktinProcTime;
-    private IThreadPoolService threadPool;
-    private ScheduledExecutorService ses;
-    private ISyncService syncService;
-    private IStoreClient<Long, SwitchSyncRepresentation> storeClient;
-
-    // Configuration options
-    protected String openFlowHost = null;
-    protected int openFlowPort = 6633;
-    protected int workerThreads = 0;
-
-
-    // This controller's current role that modules can use/query to decide
-    // if they should operate in master or slave mode.
-    // TODO: potentially we need to get rid of this field and modules must
-    // then rely on the role notifications alone...
-    protected volatile Role notifiedRole;
-
-    private static final String
-            INITIAL_ROLE_CHANGE_DESCRIPTION = "Controller startup.";
-    private RoleManager roleManager;
-    private SwitchManager switchManager;
-
-    private static final int DEFAULT_CONSOLIDATE_STORE_TIME_DELAY_MS =
-            15*1000; // 15s
-    private int consolidateStoreTimeDelayMs =
-            DEFAULT_CONSOLIDATE_STORE_TIME_DELAY_MS;
-
-
-    // Flag to always flush flow table on switch reconnect (HA or otherwise)
-    private boolean alwaysClearFlowsOnSwActivate = false;
-    private TimedCache<Long> swConnectCache;
-
-    // Storage table names
-    protected static final String CONTROLLER_TABLE_NAME = "controller_controller";
-    protected static final String CONTROLLER_ID = "id";
-
-    protected static final String SWITCH_CONFIG_TABLE_NAME = "controller_switchconfig";
-    protected static final String SWITCH_CONFIG_CORE_SWITCH = "core_switch";
-
-    protected static final String CONTROLLER_INTERFACE_TABLE_NAME = "controller_controllerinterface";
-    protected static final String CONTROLLER_INTERFACE_ID = "id";
-    protected static final String CONTROLLER_INTERFACE_CONTROLLER_ID = "controller_id";
-    protected static final String CONTROLLER_INTERFACE_TYPE = "type";
-    protected static final String CONTROLLER_INTERFACE_NUMBER = "number";
-    protected static final String CONTROLLER_INTERFACE_DISCOVERED_IP = "discovered_ip";
-
-    // FIXME: don't use "forwardingconfig" as table name
-    private static final String FLOW_PRIORITY_TABLE_NAME = "controller_forwardingconfig";
-    private static final String FLOW_COLUMN_PRIMARY_KEY = "id";
-    private static final String FLOW_VALUE_PRIMARY_KEY = "forwarding";
-    private static final String FLOW_COLUMN_ACCESS_PRIORITY = "access_priority";
-    private static final String FLOW_COLUMN_CORE_PRIORITY = "core_priority";
-    private static final String[] FLOW_COLUMN_NAMES = new String[] {
-            FLOW_COLUMN_PRIMARY_KEY,
-            FLOW_COLUMN_ACCESS_PRIORITY,
-            FLOW_COLUMN_CORE_PRIORITY
-    };
-
-    private static final short DEFAULT_ACCESS_PRIORITY = 10;
-    private static final short DEFAULT_CORE_PRIORITY = 1000;
-    private short accessPriority = DEFAULT_ACCESS_PRIORITY;
-    private short corePriority = DEFAULT_CORE_PRIORITY;
-
-
-    // Perf. related configuration
-    protected static final int SEND_BUFFER_SIZE = 128 * 1024;
-    public static final int BATCH_MAX_SIZE = 100;
-    protected static final boolean ALWAYS_DECODE_ETH = true;
-
-    // Set of port name prefixes that will be classified as uplink ports,
-    // hence will not be autoportfast.
-    Set<String> uplinkPortPrefixSet;
-
-    @Override
-    public Set<String> getUplinkPortPrefixSet() {
-        return uplinkPortPrefixSet;
-    }
-
-    public void setUplinkPortPrefixSet(Set<String> prefixSet) {
-        this.uplinkPortPrefixSet = prefixSet;
-    }
-
-    // Event IDs for debug events
-    protected IEventUpdater<SwitchEvent> evSwitch;
-
-    // Load monitor for overload protection
-    protected final boolean overload_drop =
-        Boolean.parseBoolean(System.getProperty("overload_drop", "false"));
-    protected final LoadMonitor loadmonitor = new LoadMonitor(log);
-
-    private class NotificationSwitchListener implements IOFSwitchListener {
-
-        @Override
-        public void switchAdded(long switchId) {
-            notifier.postNotification("Switch " + HexString.toHexString(switchId) + " connected.");
-        }
-
-        @Override
-        public void switchRemoved(long switchId) {
-            notifier.postNotification("Switch " + HexString.toHexString(switchId) + " disconnected.");
-        }
-
-        @Override
-        public void switchActivated(long switchId) {
-        }
-
-        @Override
-        public void switchPortChanged(long switchId, ImmutablePort port,
-                                      PortChangeType type) {
-            String msg = String.format("Switch %s port %s changed: %s",
-                                       HexString.toHexString(switchId),
-                                       port.getName(),
-                                       type.toString());
-            notifier.postNotification(msg);
-        }
-
-        @Override
-        public void switchChanged(long switchId) {
-        }
-    }
-    public static class Counters {
-        public static final String prefix = Controller.class.getPackage().getName();
-        public IDebugCounter setRoleEqual;
-        public IDebugCounter setSameRole;
-        public IDebugCounter setRoleMaster;
-        public IDebugCounter remoteStoreNotification;
-        public IDebugCounter invalidPortsChanged;
-        public IDebugCounter invalidSwitchActivatedWhileSlave;
-        public IDebugCounter invalidStoreEventWhileMaster;
-        public IDebugCounter switchDisconnectedWhileSlave;
-        public IDebugCounter switchActivated;
-        public IDebugCounter errorSameSwitchReactivated; // err
-        public IDebugCounter switchWithSameDpidActivated; // warn
-        public IDebugCounter newSwitchActivated;   // new switch
-        public IDebugCounter syncedSwitchActivated;
-        public IDebugCounter readyForReconcile;
-        public IDebugCounter newSwitchFromStore;
-        public IDebugCounter updatedSwitchFromStore;
-        public IDebugCounter switchDisconnected;
-        public IDebugCounter syncedSwitchRemoved;
-        public IDebugCounter unknownSwitchRemovedFromStore;
-        public IDebugCounter consolidateStoreRunCount;
-        public IDebugCounter consolidateStoreInconsistencies;
-        public IDebugCounter storeSyncError;
-        public IDebugCounter switchesNotReconnectingToNewMaster;
-        public IDebugCounter switchPortChanged;
-        public IDebugCounter switchOtherChange;
-        public IDebugCounter dispatchMessageWhileSlave;
-        public IDebugCounter dispatchMessage;  // does this cnt make sense? more specific?? per type? count stops?
-        public IDebugCounter controllerNodeIpsChanged;
-        public IDebugCounter messageReceived;
-        public IDebugCounter messageInputThrottled;
-        public IDebugCounter switchDisconnectReadTimeout;
-        public IDebugCounter switchDisconnectHandshakeTimeout;
-        public IDebugCounter switchDisconnectIOError;
-        public IDebugCounter switchDisconnectParseError;
-        public IDebugCounter switchDisconnectSwitchStateException;
-        public IDebugCounter rejectedExecutionException;
-        public IDebugCounter switchDisconnectOtherException;
-        public IDebugCounter switchConnected;
-        public IDebugCounter unhandledMessage;
-        public IDebugCounter packetInWhileSwitchIsSlave;
-        public IDebugCounter epermErrorWhileSwitchIsMaster;
-        public IDebugCounter roleNotResentBecauseRolePending;
-        public IDebugCounter roleRequestSent;
-        public IDebugCounter roleReplyTimeout;
-        public IDebugCounter roleReplyReceived; // expected RoleReply received
-        public IDebugCounter roleReplyErrorUnsupported;
-        public IDebugCounter switchCounterRegistrationFailed;
-
-        void createCounters(IDebugCounterService debugCounters) throws CounterException {
-            setRoleEqual =
-                debugCounters.registerCounter(
-                            prefix, "set-role-equal",
-                            "Controller received a role request with role of "+
-                            "EQUAL which is unusual",
-                            CounterType.ALWAYS_COUNT);
-            setSameRole =
-                debugCounters.registerCounter(
-                            prefix, "set-same-role",
-                            "Controller received a role request for the same " +
-                            "role the controller already had",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            setRoleMaster =
-                debugCounters.registerCounter(
-                            prefix, "set-role-master",
-                            "Controller received a role request with role of " +
-                            "MASTER. This counter can be at most 1.",
-                            CounterType.ALWAYS_COUNT);
-
-            remoteStoreNotification =
-                debugCounters.registerCounter(
-                            prefix, "remote-store-notification",
-                            "Received a notification from the sync service " +
-                            "indicating that switch information has changed",
-                            CounterType.ALWAYS_COUNT);
-
-            invalidPortsChanged =
-                debugCounters.registerCounter(
-                            prefix, "invalid-ports-changed",
-                            "Received an unexpected ports changed " +
-                            "notification while the controller was in " +
-                            "SLAVE role.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            invalidSwitchActivatedWhileSlave =
-                debugCounters.registerCounter(
-                            prefix, "invalid-switch-activated-while-slave",
-                            "Received an unexpected switchActivated " +
-                            "notification while the controller was in " +
-                            "SLAVE role.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            invalidStoreEventWhileMaster =
-                debugCounters.registerCounter(
-                            prefix, "invalid-store-event-while-master",
-                            "Received an unexpected notification from " +
-                            "the sync store while the controller was in " +
-                            "MASTER role.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            switchDisconnectedWhileSlave =
-                debugCounters.registerCounter(
-                            prefix, "switch-disconnected-while-slave",
-                            "A switch disconnected and the controller was " +
-                            "in SLAVE role.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            switchActivated =
-                debugCounters.registerCounter(
-                            prefix, "switch-activated",
-                            "A switch connected to this controller is now " +
-                            "in MASTER role",
-                            CounterType.ALWAYS_COUNT);
-
-            errorSameSwitchReactivated = // err
-                debugCounters.registerCounter(
-                            prefix, "error-same-switch-reactivated",
-                            "A switch that was already in active state " +
-                            "was activated again. This indicates a " +
-                            "controller defect",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-
-            switchWithSameDpidActivated = // warn
-                debugCounters.registerCounter(
-                            prefix, "switch-with-same-dpid-activated",
-                            "A switch with the same DPID as another switch " +
-                            "connected to the controller. This can be " +
-                            "caused by multiple switches configured with " +
-                            "the same DPID or by a switch reconnecting very " +
-                            "quickly.",
-                            CounterType.COUNT_ON_DEMAND,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            newSwitchActivated =   // new switch
-                debugCounters.registerCounter(
-                            prefix, "new-switch-activated",
-                            "A new switch has completed the handshake as " +
-                            "MASTER. The switch was not known to any other " +
-                            "controller in the cluster",
-                            CounterType.ALWAYS_COUNT);
-            syncedSwitchActivated =
-                debugCounters.registerCounter(
-                            prefix, "synced-switch-activated",
-                            "A switch has completed the handshake as " +
-                            "MASTER. The switch was known to another " +
-                            "controller in the cluster",
-                            CounterType.ALWAYS_COUNT);
-
-            readyForReconcile =
-                debugCounters.registerCounter(
-                            prefix, "ready-for-reconcile",
-                            "Controller is ready for flow reconciliation " +
-                            "after Slave to Master transition. Either all " +
-                            "previously known switches are now active " +
-                            "or they have timed out and have been removed." +
-                            "This counter will be 0 or 1.",
-                            CounterType.ALWAYS_COUNT);
-
-            newSwitchFromStore =
-                debugCounters.registerCounter(
-                            prefix, "new-switch-from-store",
-                            "A new switch has connected to another " +
-                            "another controller in the cluster. This " +
-                            "controller instance has received a sync store " +
-                            "notification for it.",
-                            CounterType.ALWAYS_COUNT);
-
-            updatedSwitchFromStore =
-                debugCounters.registerCounter(
-                            prefix, "updated-switch-from-store",
-                            "Information about a switch connected to " +
-                            "another controller instance was updated in " +
-                            "the sync store. This controller instance has " +
-                            "received a notification for it",
-                            CounterType.ALWAYS_COUNT);
-
-            switchDisconnected =
-                debugCounters.registerCounter(
-                            prefix, "switch-disconnected",
-                            "FIXME: switch has disconnected",
-                            CounterType.ALWAYS_COUNT);
-
-            syncedSwitchRemoved =
-                debugCounters.registerCounter(
-                            prefix, "synced-switch-removed",
-                            "A switch connected to another controller " +
-                            "instance has disconnected from the controller " +
-                            "cluster. This controller instance has " +
-                            "received a notification for it",
-                            CounterType.ALWAYS_COUNT);
-
-            unknownSwitchRemovedFromStore =
-                debugCounters.registerCounter(
-                            prefix, "unknown-switch-removed-from-store",
-                            "This controller instances has received a sync " +
-                            "store notification that a switch has " +
-                            "disconnected but this controller instance " +
-                            "did not have the any information about the " +
-                            "switch", // might be less than warning
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            consolidateStoreRunCount =
-                debugCounters.registerCounter(
-                            prefix, "consolidate-store-run-count",
-                            "This controller has transitioned from SLAVE " +
-                            "to MASTER and waited for switches to reconnect. " +
-                            "The controller has finished waiting and has " +
-                            "reconciled switch entries in the sync store " +
-                            "with live state",
-                            CounterType.ALWAYS_COUNT);
-
-            consolidateStoreInconsistencies =
-                    debugCounters.registerCounter(
-                                prefix, "consolidate-store-inconsistencies",
-                                "During switch sync store consolidation: " +
-                                "Number of switches that were in the store " +
-                                "but not otherwise known plus number of " +
-                                "switches that were in the store previously " +
-                                "but are now missing plus number of "  +
-                                "connected switches that were absent from " +
-                                "the store although this controller has " +
-                                "written them. A non-zero count " +
-                                "indicates a brief split-brain dual MASTER " +
-                                "situation during fail-over",
-                                CounterType.ALWAYS_COUNT);
-
-            storeSyncError =
-                debugCounters.registerCounter(
-                            prefix, "store-sync-error",
-                            "Number of times a sync store operation failed " +
-                            "due to a store sync exception or an entry in " +
-                            "in the store had invalid data.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-
-            switchesNotReconnectingToNewMaster =
-                debugCounters.registerCounter(
-                            prefix, "switches-not-reconnecting-to-new-master",
-                            "Switches that were connected to another " +
-                            "controller instance in the cluster but that " +
-                            "did not reconnect to this controller after it " +
-                            "transitioned to MASTER", // might be less than warning
-                            CounterType.ALWAYS_COUNT);
-
-            switchPortChanged =
-                debugCounters.registerCounter(
-                            prefix, "switch-port-changed",
-                            "Number of times switch ports have changed",
-                            CounterType.ALWAYS_COUNT);
-            switchOtherChange =
-                debugCounters.registerCounter(
-                            prefix, "switch-other-change",
-                            "Number of times other information of a switch " +
-                            "has changed.",
-                            CounterType.ALWAYS_COUNT);
-
-            dispatchMessageWhileSlave =
-                debugCounters.registerCounter(
-                            prefix, "dispatch-message-while-slave",
-                            "Number of times an OF message was received " +
-                            "and supposed to be dispatched but the " +
-                            "controller was in SLAVE role and the message " +
-                            "was not dispatched",
-                            CounterType.ALWAYS_COUNT);
-
-            dispatchMessage =  // does this cnt make sense? more specific?? per type? count stops?
-                debugCounters.registerCounter(
-                            prefix, "dispatch-message",
-                            "Number of times an OF message was dispatched " +
-                            "to registered modules",
-                            CounterType.ALWAYS_COUNT);
-
-            controllerNodeIpsChanged =
-                debugCounters.registerCounter(
-                            prefix, "controller-nodes-ips-changed",
-                            "IP addresses of controller nodes have changed",
-                            CounterType.ALWAYS_COUNT);
-
-        //------------------------
-        // channel handler counters. Factor them out ??
-            messageReceived =
-                debugCounters.registerCounter(
-                            prefix, "message-received",
-                            "Number of OpenFlow messages received. Some of " +
-                            "these might be throttled",
-                            CounterType.ALWAYS_COUNT);
-            messageInputThrottled =
-                debugCounters.registerCounter(
-                            prefix, "message-input-throttled",
-                            "Number of OpenFlow messages that were " +
-                            "throttled due to high load from the sender",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-        // TODO: more counters in messageReceived ??
-
-            switchDisconnectReadTimeout =
-                debugCounters.registerCounter(
-                            prefix, "switch-disconnect-read-timeout",
-                            "Number of times a switch was disconnected due " +
-                            "due the switch failing to send OpenFlow " +
-                            "messages or responding to OpenFlow ECHOs",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-            switchDisconnectHandshakeTimeout =
-                debugCounters.registerCounter(
-                            prefix, "switch-disconnect-handshake-timeout",
-                            "Number of times a switch was disconnected " +
-                            "because it failed to complete the handshake " +
-                            "in time.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-            switchDisconnectIOError =
-                debugCounters.registerCounter(
-                            prefix, "switch-disconnect-io-error",
-                            "Number of times a switch was disconnected " +
-                            "due to IO errors on the switch connection.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-            switchDisconnectParseError =
-                debugCounters.registerCounter(
-                            prefix, "switch-disconnect-parse-error",
-                           "Number of times a switch was disconnected " +
-                           "because it sent an invalid packet that could " +
-                           "not be parsed",
-                           CounterType.ALWAYS_COUNT,
-                           IDebugCounterService.CTR_MDATA_ERROR);
-
-            switchDisconnectSwitchStateException =
-                debugCounters.registerCounter(
-                            prefix, "switch-disconnect-switch-state-exception",
-                            "Number of times a switch was disconnected " +
-                            "because it sent messages that were invalid " +
-                            "given the switch connection's state.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-            rejectedExecutionException =
-                debugCounters.registerCounter(
-                            prefix, "rejected-execution-exception",
-                            "TODO",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-
-            switchDisconnectOtherException =
-                debugCounters.registerCounter(
-                            prefix,  "switch-disconnect-other-exception",
-                            "Number of times a switch was disconnected " +
-                            "due to an exceptional situation not covered " +
-                            "by other counters",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_ERROR);
-
-            switchConnected =
-                debugCounters.registerCounter(
-                            prefix, "switch-connected",
-                            "Number of times a new switch connection was " +
-                            "established",
-                            CounterType.ALWAYS_COUNT);
-
-            unhandledMessage =
-                debugCounters.registerCounter(
-                            prefix, "unhandled-message",
-                            "Number of times an OpenFlow message was " +
-                            "received that the controller ignored because " +
-                            "it was inapproriate given the switch " +
-                            "connection's state.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-                            // might be less than warning
-
-            packetInWhileSwitchIsSlave =
-                debugCounters.registerCounter(
-                            prefix, "packet-in-while-switch-is-slave",
-                            "Number of times a packet in was received " +
-                            "from a switch that was in SLAVE role. " +
-                            "Possibly inidicates inconsistent roles.",
-                            CounterType.ALWAYS_COUNT);
-            epermErrorWhileSwitchIsMaster =
-                debugCounters.registerCounter(
-                            prefix, "eperm-error-while-switch-is-master",
-                            "Number of times a permission error was " +
-                            "received while the switch was in MASTER role. " +
-                            "Possibly inidicates inconsistent roles.",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            roleNotResentBecauseRolePending =
-                debugCounters.registerCounter(
-                            prefix, "role-not-resent-because-role-pending",
-                            "The controller tried to reestablish a role " +
-                            "with a switch but did not do so because a " +
-                            "previous role request was still pending",
-                            CounterType.ALWAYS_COUNT);
-            roleRequestSent =
-                debugCounters.registerCounter(
-                            prefix, "role-request-sent",
-                            "Number of times the controller sent a role " +
-                            "request to a switch.",
-                            CounterType.ALWAYS_COUNT);
-            roleReplyTimeout =
-                debugCounters.registerCounter(
-                            prefix, "role-reply-timeout",
-                            "Number of times a role request message did not " +
-                            "receive the expected reply from a switch",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-
-            roleReplyReceived = // expected RoleReply received
-                debugCounters.registerCounter(
-                            prefix, "role-reply-received",
-                            "Number of times the controller received the " +
-                            "expected role reply message from a switch",
-                            CounterType.ALWAYS_COUNT);
-
-            roleReplyErrorUnsupported =
-                debugCounters.registerCounter(
-                            prefix, "role-reply-error-unsupported",
-                            "Number of times the controller received an " +
-                            "error from a switch in response to a role " +
-                            "request indicating that the switch does not " +
-                            "support roles.",
-                            CounterType.ALWAYS_COUNT);
-
-            switchCounterRegistrationFailed =
-                debugCounters.registerCounter(prefix,
-                            "switch-counter-registration-failed",
-                            "Number of times the controller failed to " +
-                            "register per-switch debug counters",
-                            CounterType.ALWAYS_COUNT,
-                            IDebugCounterService.CTR_MDATA_WARN);
-        }
-    }
-
-    private Counters counters;
-
-    Counters getCounters() {
-        return this.counters;
-    }
-
-    /**
-     * A utility class to manage the <i>controller roles</i>.
-     *
-     * A utility class to manage the <i>controller roles</i>  as opposed
-     * to the switch roles. The class manages the controllers current role,
-     * handles role change requests, and maintains the list of connected
-     * switch(-channel) so it can notify the switches of role changes.
-     *
-     * We need to ensure that every connected switch is always send the
-     * correct role. Therefore, switch add, sending of the intial role, and
-     * changing role need to use mutexes to ensure this. This has the ugly
-     * side-effect of requiring calls between controller and OFChannelHandler
-     *
-     * This class is fully thread safe. Its method can safely be called from
-     * any thread.
-     *
-     * @author gregor
-     *
-     */
-    private class RoleManager {
-        // This role represents the role that has been set by setRole. This
-        // role might or might now have been notified to listeners just yet.
-        // This is updated by setRole. doSetRole() will use this value as
-        private Role role;
-        private String roleChangeDescription;
-
-        // The current role info. This is updated /after/ dampening
-        // switches and
-        // listener notifications have been enqueued (but potentially before
-        // they have been dispatched)
-        private RoleInfo currentRoleInfo;
-        private final Set<OFChannelHandler> connectedChannelHandlers;
-
-        /**
-         * @param role initial role
-         * @param roleChangeDescription initial value of the change description
-         * @throws NullPointerException if role or roleChangeDescription is null
-         * @throws IllegalArgumentException if role is EQUAL
-         */
-        public RoleManager(Role role, String roleChangeDescription) {
-            if (role == null)
-                throw new NullPointerException("role must not be null");
-            if (role == Role.EQUAL)
-                throw new IllegalArgumentException("role must not be EQUAL");
-            if (roleChangeDescription == null) {
-                throw new NullPointerException("roleChangeDescription must " +
-                                               "not be null");
-            }
-
-            this.role = role;
-            this.roleChangeDescription = roleChangeDescription;
-            this.connectedChannelHandlers = new HashSet<OFChannelHandler>();
-            this.currentRoleInfo = new RoleInfo(this.role,
-                                           this.roleChangeDescription,
-                                           new Date());
-        }
-
-        /**
-         * Add a newly connected OFChannelHandler. The channel handler is added
-         * we send the current role to the channel handler. All subsequent role
-         * changes will be send to all connected
-         * @param h The OFChannelHandler to add
-         */
-        public synchronized void
-                addOFChannelHandlerAndSendRole(OFChannelHandler h) {
-            connectedChannelHandlers.add(h);
-            h.sendRoleRequest(this.role);
-        }
-
-        /**
-         * Remove OFChannelHandler. E.g., due do disconnect.
-         * @param h The OFChannelHandler to remove.
-         */
-        public synchronized void removeOFChannelHandler(OFChannelHandler h) {
-            connectedChannelHandlers.remove(h);
-        }
-
-        /**
-         * Re-assert a role for the given channel handler.
-         *
-         * The caller specifies the role that should be reasserted. We only
-         * reassert the role if the controller's current role matches the
-         * reasserted role and there is no role request for the reasserted role
-         * pending.
-         * @param h The OFChannelHandler on which we should reassert.
-         * @param role The role to reassert
-         */
-        public synchronized void reassertRole(OFChannelHandler h, Role role) {
-            // check if the requested reassertion actually makes sense
-            if (this.role != role)
-                return;
-            h.sendRoleRequestIfNotPending(this.role);
-        }
-
-        /**
-         * Set the controller's new role and notify switches.
-         *
-         * This method updates the controllers current role and notifies all
-         * connected switches of the new role is different from the current
-         * role. We dampen calls to this method. See class description for
-         * details.
-         *
-         * @param role The new role.
-         * @param roleChangeDescription A textual description of why the role
-         * was changed. For information purposes only.
-         * @throws NullPointerException if role or roleChangeDescription is null
-         */
-        public synchronized void setRole(Role role, String roleChangeDescription) {
-            if (role == null)
-                throw new NullPointerException("role must not be null");
-            if (roleChangeDescription == null) {
-                throw new NullPointerException("roleChangeDescription must " +
-                                               "not be null");
-            }
-            if (role == Role.EQUAL) {
-                counters.setRoleEqual.updateCounterWithFlush();
-                log.debug("Received role request for EQUAL, setting to MASTER"
-                          + " instead");
-                role = Role.MASTER;
-            }
-            if (role == this.role) {
-                counters.setSameRole.updateCounterWithFlush();
-                log.debug("Received role request for {} but controller is "
-                        + "already {}. Ignoring it.", role, this.role);
-                return;
-            }
-            if (this.role == Role.MASTER && role == Role.SLAVE) {
-                log.info("Received role request to transition from MASTER to "
-                          + " SLAVE (reason: {}). Terminating floodlight.",
-                          roleChangeDescription);
-                System.exit(0);
-            }
-
-            // At this point we are guaranteed that we will execute the code
-            // below exactly once during the lifetime of this process! And
-            // it will be a to MASTER transition
-            counters.setRoleMaster.updateCounterWithFlush();
-            log.info("Received role request for {} (reason: {})."
-                     + " Initiating transition", role, roleChangeDescription);
-
-            this.role = role;
-            this.roleChangeDescription = roleChangeDescription;
-
-            // TODO: we currently notify switches synchronously from the REST
-            // API handler. We could (should?) do this asynchronously.
-            currentRoleInfo = new RoleInfo(this.role,
-                                           this.roleChangeDescription,
-                                           new Date());
-            Controller.this.switchManager.setRole(this.role);
-            for (OFChannelHandler h: connectedChannelHandlers)
-                h.sendRoleRequest(this.role);
-
-            Controller.this.addUpdateToQueue(new HARoleUpdate(this.role));
-        }
-
-        /**
-         * Return the RoleInfo object describing the current role.
-         *
-         * Return the RoleInfo object describing the current role. The
-         * RoleInfo object is used by REST API users. We need to return
-         * a defensive copy.
-         * @return the current RoleInfo object
-         */
-        public synchronized RoleInfo getRoleInfo() {
-            return new RoleInfo(currentRoleInfo);
-        }
-    }
-
-
-    /**
-     * This is a utility class to encapsulate code that deals with switch
-     * life cycles. It interacts with the sync store to read/write switches
-     * to/from the store and it maintains the switch maps.
-     * @author gregor
-     *
-     */
-    private class SwitchManager implements IStoreListener<Long> {
-        private Role role;
-        private final ConcurrentHashMap<Long,IOFSwitch> activeSwitches;
-        private final ConcurrentHashMap<Long,IOFSwitch> syncedSwitches;
-
-        public SwitchManager(Role role) {
-            this.role = role;
-            this.activeSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
-            this.syncedSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
-       }
-
-        @Override
-        public void keysModified(Iterator<Long> keys, UpdateType type) {
-            if (type == UpdateType.LOCAL) {
-                // We only care for remote updates
-                return;
-            }
-            counters.remoteStoreNotification.updateCounterWithFlush();
-            while(keys.hasNext()) {
-                Long key = keys.next();
-                Versioned<SwitchSyncRepresentation> versionedSwitch = null;
-                try {
-                    versionedSwitch = storeClient.get(key);
-                } catch (SyncException e) {
-                    counters.storeSyncError.updateCounterWithFlush();
-                    log.error("Exception while retrieving switch " +
-                              HexString.toHexString(key) +
-                              " from sync store. Skipping", e);
-                    continue;
-                }
-                if (log.isTraceEnabled()) {
-                    log.trace("Reveiced switch store notification: key={}, " +
-                               "entry={}", key, versionedSwitch.getValue());
-                }
-                // versionedSwtich won't be null. storeClient.get() always
-                // returns a non-null or throws an exception
-                if (versionedSwitch.getValue() == null) {
-                    switchRemovedFromStore(key);
-                    continue;
-                }
-                SwitchSyncRepresentation storedSwitch =
-                        versionedSwitch.getValue();
-                IOFSwitch sw = getOFSwitchInstance(storedSwitch.getDescription());
-                sw.setFeaturesReply(storedSwitch.getFeaturesReply());
-                if (!key.equals(storedSwitch.getFeaturesReply().getDatapathId())) {
-                    counters.storeSyncError.updateCounterWithFlush();
-                    log.error("Inconsistent DPIDs from switch sync store: " +
-                              "key is {} but sw.getId() says {}. Ignoring",
-                              HexString.toHexString(key), sw.getStringId());
-                    continue;
-                }
-                switchAddedToStore(sw);
-            }
-        }
-
-
-        public synchronized void setRole(Role role) {
-            this.role = role;
-            Runnable consolidateStoreTask = new Runnable() {
-                @Override
-                public void run() {
-                    consolidateStore();
-                }
-            };
-            if ((role == Role.MASTER) &&
-                    this.syncedSwitches.isEmpty())
-                addUpdateToQueue(new ReadyForReconcileUpdate());
-
-            Controller.this.ses.schedule(consolidateStoreTask,
-                                         consolidateStoreTimeDelayMs,
-                                         TimeUnit.MILLISECONDS);
-        }
-
-        @LogMessageDocs({
-        @LogMessageDoc(level="ERROR",
-                message="Switch {switch} activated but was already active",
-                explanation="A switch that was already activated was " +
-                            "activated again. This should not happen.",
-                recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG
-                ),
-        @LogMessageDoc(level="WARN",
-                message="New switch added {switch} for already-added switch {switch}",
-                explanation="A switch with the same DPID as another switch " +
-                        "connected to the controller.  This can be caused by " +
-                        "multiple switches configured with the same DPID, or " +
-                        "by a switch reconnected very quickly after " +
-                        "disconnecting.",
-                recommendation="If this happens repeatedly, it is likely there " +
-                        "are switches with duplicate DPIDs on the network.  " +
-                        "Reconfigure the appropriate switches.  If it happens " +
-                        "very rarely, then it is likely this is a transient " +
-                        "network problem that can be ignored."
-                )
-        })
-        /**
-         * Called when a switch is activated, i.e., when it enters master
-         * role relative to this controller.
-         * @param sw
-         */
-        public synchronized void switchActivated(IOFSwitch sw) {
-            if (role != Role.MASTER) {
-                counters.invalidSwitchActivatedWhileSlave.updateCounterWithFlush();
-                return; // only react to switch connections when master
-                // FIXME: should we disconnect the switch? When can this happen?
-            }
-            Long dpid = sw.getId();
-            counters.switchActivated.updateCounterWithFlush();
-            IOFSwitch oldSw = this.activeSwitches.put(dpid, sw);
-            // Update event history
-            evSwitch.updateEventWithFlush(new SwitchEvent(dpid, "connected"));
-
-            if (oldSw == sw)  {
-                // Note == for object equality, not .equals for value
-                // TODO: should we wipe the flow table if
-                // alwaysClearFlowsOnSwAdd is set? OTOH this case should
-                // really never happen.
-                counters.errorSameSwitchReactivated.updateCounterWithFlush();
-                log.error("Switch {} activated but was already active", sw);
-                addSwitchToStore(sw);
-                return;
-            }
-
-            if (oldSw != null) {
-                // This happens either when we have switches with duplicate
-                // DPIDs or when a switch reconnects before we saw the
-                // disconnect
-                counters.switchWithSameDpidActivated.updateCounterWithFlush();
-                log.warn("New switch added {} for already-added switch {}",
-                          sw, oldSw);
-                // We need to disconnect and remove the old switch
-                // TODO: we notify switch listeners that the switch has been
-                // removed and then we notify them that the new one has been
-                // added. One could argue that a switchChanged notification
-                // might be more appropriate in this case....
-                oldSw.cancelAllStatisticsReplies();
-                addUpdateToQueue(new SwitchUpdate(dpid,
-                                                  SwitchUpdateType.REMOVED));
-                oldSw.disconnectOutputStream();
-                // Add the new switch and clear FlowMods
-                // TODO: if this is the same switch re-connecting rather than
-                // a DPID collision it would make sense to not wipe the flow
-                // table.
-                sw.clearAllFlowMods();
-                addUpdateToQueue(new SwitchUpdate(dpid,
-                                                  SwitchUpdateType.ADDED));
-                addUpdateToQueue(new SwitchUpdate(dpid,
-                                                  SwitchUpdateType.ACTIVATED));
-                addSwitchToStore(sw);
-                return;
-            }
-
-            IOFSwitch storedSwitch = this.syncedSwitches.remove(sw.getId());
-            if (storedSwitch == null) {
-                // The switch isn't known to the controller cluster. We
-                // need to send a switchAdded notification and clear all
-                // flows.
-                if (!swConnectCache.update(sw.getId()))
-                    sw.clearAllFlowMods();
-                addUpdateToQueue(new SwitchUpdate(dpid,
-                                                  SwitchUpdateType.ADDED));
-                addUpdateToQueue(new SwitchUpdate(dpid,
-                                                  SwitchUpdateType.ACTIVATED));
-                counters.newSwitchActivated.updateCounterWithFlush();
-            } else {
-                // FIXME: switch was in store. check if ports or anything else
-                // has changed and send update.
-                if (alwaysClearFlowsOnSwActivate) {
-                    sw.clearAllFlowMods();
-                }
-                if (sw.attributeEquals(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true)) {
-                    // We have a stored switch and the newly activated switch
-                    // supports roles. This indicates that the switch was
-                    // previously connected as slave. Since we don't update
-                    // ports while slave, we need to set the ports on the
-                    // new switch from the ports on the stored switch
-                    // No need to send notifications, since we've dispatched
-                    // them as we receive them from the store
-                    sw.setPorts(storedSwitch.getPorts());
-                }
-                addUpdateToQueue(new SwitchUpdate(dpid,
-                                                  SwitchUpdateType.ACTIVATED));
-                sendNotificationsIfSwitchDiffers(storedSwitch, sw);
-                counters.syncedSwitchActivated.updateCounterWithFlush();
-                if (this.syncedSwitches.isEmpty()) {
-                    // we have just activated the last synced switch. I.e.,
-                    // all previously known switch are now active. Send
-                    // notification
-                    // update dispatcher will increment counter
-                    addUpdateToQueue(new ReadyForReconcileUpdate());
-                }
-            }
-            addSwitchToStore(sw);
-        }
-
-        /**
-         * Called when ports on the given switch have changed. Writes the
-         * updated switch to the sync store and queues a switch notification
-         * to listeners
-         * @param sw
-         */
-        public synchronized void switchPortsChanged(IOFSwitch sw,
-                                                    ImmutablePort port,
-                                                    PortChangeType type) {
-            if (role != Role.MASTER) {
-                counters.invalidPortsChanged.updateCounterWithFlush();
-                return;
-            }
-            if (!this.activeSwitches.containsKey(sw.getId())) {
-                counters.invalidPortsChanged.updateCounterWithFlush();
-                return;
-            }
-            // update switch in store
-            addSwitchToStore(sw);
-            // no need to count here. SwitchUpdate.dispatch will count
-            // the portchanged
-            SwitchUpdate update = new SwitchUpdate(sw.getId(),
-                                                   SwitchUpdateType.PORTCHANGED,
-                                                   port, type);
-            addUpdateToQueue(update);
-        }
-
-        /**
-         * Called when we receive a store notification about a new or updated
-         * switch.
-         * @param sw
-         */
-        private synchronized void switchAddedToStore(IOFSwitch sw) {
-            if (role != Role.SLAVE) {
-                counters.invalidStoreEventWhileMaster.updateCounterWithFlush();
-                return; // only read from store if slave
-            }
-            Long dpid = sw.getId();
-
-            IOFSwitch oldSw = syncedSwitches.put(dpid, sw);
-            if (oldSw == null)  {
-                counters.newSwitchFromStore.updateCounterWithFlush();
-                addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED));
-            } else {
-                // The switch already exists in storage, see if anything
-                // has changed
-                sendNotificationsIfSwitchDiffers(oldSw, sw);
-                counters.updatedSwitchFromStore.updateCounterWithFlush();
-            }
-        }
-
-        /**
-         * Called when we receive a store notification about a switch that
-         * has been removed from the sync store
-         * @param dpid
-         */
-        private synchronized void switchRemovedFromStore(long dpid) {
-            if (role != Role.SLAVE) {
-                counters.invalidStoreEventWhileMaster.updateCounterWithFlush();
-                return; // only read from store if slave
-            }
-            IOFSwitch oldSw = syncedSwitches.remove(dpid);
-            if (oldSw != null) {
-                counters.syncedSwitchRemoved.updateCounterWithFlush();
-                addUpdateToQueue(new SwitchUpdate(dpid,
-                                                  SwitchUpdateType.REMOVED));
-            } else {
-                // TODO: the switch was deleted (tombstone) before we ever
-                // knew about it (or was deleted repeatedly). Can this
-                // happen? When/how?
-                counters.unknownSwitchRemovedFromStore.updateCounterWithFlush();
-            }
-        }
-
-        public synchronized void switchDeactivated(IOFSwitch sw) {
-            // ignore. we don't handle MASTER -> SLAVE transitions. We
-            // expect a restart
-        }
-
-        /**
-         * Called when a switch disconnects
-         * @param sw
-         */
-        public synchronized void switchDisconnected(IOFSwitch sw) {
-            if (role == Role.SLAVE) {
-                counters.switchDisconnectedWhileSlave.updateCounterWithFlush();
-                return; // only react to switch connections when master
-            }
-            long dpid = sw.getId();
-            // Update event history
-            // TODO: this is asymmetric with respect to connect event
-            //       in switchActivated(). Should we have events on the
-            //       slave as well?
-            evSwitch.updateEventWithFlush(new SwitchEvent(dpid, "disconnected"));
-            counters.switchDisconnected.updateCounterWithFlush();
-            IOFSwitch oldSw = this.activeSwitches.get(dpid);
-            if (oldSw != sw) {
-                // This can happen if the disconnected switch was inactive
-                // (SLAVE) then oldSw==null. Or if we previously had the
-                // "added switch for already added switch case".
-                // Either way we shouldn't notify or do anything else
-                log.debug("removeSwitch called for switch {} but have {} in"
-                          + " activeSwitches map. Ignoring", sw, oldSw);
-                return;
-            }
-            log.debug("removeSwitch {}", sw);
-            swConnectCache.update(sw.getId());
-            this.activeSwitches.remove(sw.getId());
-            removeSwitchFromStore(sw.getId());
-            // We cancel all outstanding statistics replies if the switch transition
-            // from active. In the future we might allow statistics requests
-            // from slave controllers. Then we need to move this cancelation
-            // to switch disconnect
-            sw.cancelAllStatisticsReplies();
-            addUpdateToQueue(new SwitchUpdate(sw.getId(),
-                                              SwitchUpdateType.REMOVED));
-        }
-
-        /**
-         * Write the given switch to the sync store.
-         * @param sw
-         */
-        private synchronized void addSwitchToStore(IOFSwitch sw) {
-            // Add to store
-            // FIXME: do we need to use a put that takes a versioned here?
-            // need to verify
-            try {
-                storeClient.put(sw.getId(), new SwitchSyncRepresentation(sw));
-            } catch (ObsoleteVersionException e) {
-                // FIXME: what's the right behavior here. Can the store client
-                // even throw this error? Should not since all local store
-                // access is synchronized
-            } catch (SyncException e) {
-                counters.storeSyncError.updateCounterWithFlush();
-                log.error("Could not write switch " + sw.getStringId() +
-                          " to sync store:", e);
-            }
-        }
-
-        /**
-         * Write the given switch to the sync store if it's not already
-         * there
-         * TODO: should this be merged with addSwitchToStore
-         * @param sw
-         * @return true if the switch was absent, false otherwise
-         */
-        private synchronized boolean addSwitchToStoreIfAbsent(IOFSwitch sw) {
-            try {
-                Versioned<SwitchSyncRepresentation> versionedSSr =
-                        storeClient.get(sw.getId());
-                if (versionedSSr.getValue() == null) {
-                    // switch is absent
-                    versionedSSr.setValue(new SwitchSyncRepresentation(sw));
-                    storeClient.put(sw.getId(), versionedSSr);
-                    return true;
-                } else {
-                    return false;
-                }
-            } catch (ObsoleteVersionException e) {
-                // FIXME: what's the right behavior here. Can the store client
-                // even throw this error? Should not since all local store
-                // access is synchronized
-            } catch (SyncException e) {
-                counters.storeSyncError.updateCounterWithFlush();
-                log.error("Could not write switch " + sw.getStringId() +
-                          " to sync store:", e);
-            }
-            return false;
-        }
-
-        /**
-         * Remove the given switch from the sync store.
-         * @param dpid
-         */
-        private synchronized void removeSwitchFromStore(long dpid) {
-            try {
-                storeClient.delete(dpid);
-            } catch (SyncException e) {
-                counters.storeSyncError.updateCounterWithFlush();
-                // ObsoleteVerisonException can't happend because all
-                // store modifications are synchronized
-                log.error("Could not remove switch " +
-                          HexString.toHexString(dpid) +
-                          " from sync store:", e);
-            }
-        }
-
-        /**
-         * Check if the two switches differ in their ports or in other
-         * fields and if they differ enqueue a switch update
-         * @param oldSw
-         * @param newSw
-         */
-        private synchronized void
-                sendNotificationsIfSwitchDiffers(IOFSwitch oldSw,
-                                                 IOFSwitch newSw) {
-            Collection<PortChangeEvent> portDiffs =
-                    oldSw.comparePorts(newSw.getPorts());
-            for (PortChangeEvent ev: portDiffs) {
-                SwitchUpdate update =
-                        new SwitchUpdate(newSw.getId(),
-                                         SwitchUpdateType.PORTCHANGED,
-                                         ev.port, ev.type);
-                addUpdateToQueue(update);
-            }
-        }
-        /**
-         * Remove all entries from the store that don't correspond to an
-         * active switch.
-         * TODO: is it a problem that this is fully synchronized
-         */
-        private synchronized void consolidateStore() {
-            if (role == Role.SLAVE)
-                return;
-            boolean shouldNotifyReadyForReconcile = false;
-            counters.consolidateStoreRunCount.updateCounterWithFlush();
-            log.info("Consolidating synced switches after MASTER transition");
-            IClosableIterator<Map.Entry<Long,Versioned<SwitchSyncRepresentation>>>
-                    iter = null;
-            try {
-                iter = storeClient.entries();
-            } catch (SyncException e) {
-                counters.storeSyncError.updateCounterWithFlush();
-                log.error("Failed to read switches from sync store", e);
-                return;
-            }
-            try {
-                while(iter.hasNext()) {
-                    Entry<Long, Versioned<SwitchSyncRepresentation>> entry =
-                            iter.next();
-                    if (!this.activeSwitches.containsKey(entry.getKey())) {
-                        removeSwitchFromStore(entry.getKey());
-                        if (this.syncedSwitches.remove(entry.getKey()) != null) {
-                            // a switch that's in the store and in synced
-                            // switches but that is not active. I.e., a
-                            // switch known to the old master that hasn't
-                            // reconnected to this controller.
-                            counters.switchesNotReconnectingToNewMaster
-                                    .updateCounterWithFlush();
-                            shouldNotifyReadyForReconcile = true;
-                            addUpdateToQueue(new SwitchUpdate(entry.getKey(),
-                                                     SwitchUpdateType.REMOVED));
-                        } else {
-                            // A switch was in the store but it's neither in
-                            // activeSwitches nor syncedSwitches. This could
-                            // happen if the old Master has added this entry
-                            // to the store after this controller has
-                            // stopped reacting to store notifications (due
-                            // to MASTER transition)
-                            counters.consolidateStoreInconsistencies
-                                    .updateCounterWithFlush();
-                        }
-                    }
-                }
-            } finally {
-                if (iter != null)
-                    iter.close();
-            }
-            // In general, syncedSwitches should now be empty. However,
-            // the old Master could have removed a switch from the store
-            // after this controller has stopped reacting to store
-            // notification (because it's now MASTER). We need to remove
-            // these switches.
-            Iterator<Long> it = this.syncedSwitches.keySet().iterator();
-            while (it.hasNext()) {
-                counters.switchesNotReconnectingToNewMaster.updateCounterWithFlush();
-                counters.consolidateStoreInconsistencies.updateCounterWithFlush();
-                Long dpid = it.next();
-                shouldNotifyReadyForReconcile = true;
-                addUpdateToQueue(new SwitchUpdate(dpid,
-                                                  SwitchUpdateType.REMOVED));
-                it.remove();
-            }
-            if (shouldNotifyReadyForReconcile) {
-                // at least one previously known switch has been removed.
-                addUpdateToQueue(new ReadyForReconcileUpdate());
-            }
-
-            // FIXME: do we need this final check here.
-            // Now iterate through all active switches and determine if
-            // any of them are missing from the sync store. This can only
-            // happen if another controller has removed them (because we know
-            // that we have written them to the store).
-            for (IOFSwitch sw: this.activeSwitches.values()) {
-                if (addSwitchToStoreIfAbsent(sw))
-                    counters.consolidateStoreInconsistencies.updateCounterWithFlush();
-            }
-        }
-
-        // FIXME: remove this method
-        public Map<Long,IOFSwitch> getAllSwitchMap() {
-            // this.syncedSwitches will be empty after the master transition
-            Map<Long,IOFSwitch> switches =
-                    new HashMap<Long, IOFSwitch>(this.syncedSwitches);
-            if (this.role != Role.SLAVE)
-                switches.putAll(this.activeSwitches);
-            return switches;
-        }
-
-        public Set<Long> getAllSwitchDpids() {
-            // this.syncedSwitches will be empty after the master transition
-            Set<Long> dpids = new HashSet<Long>(this.syncedSwitches.keySet());
-            if (this.role != Role.SLAVE)
-                dpids.addAll(this.activeSwitches.keySet());
-            return dpids;
-        }
-
-        public IOFSwitch getSwitch(long dpid) {
-            if (this.role == Role.SLAVE)
-                return this.syncedSwitches.get(dpid);
-            // MASTER: if the switch is found in the active map return
-            // otherwise look up the switch in the bigSync map. The bigSync map
-            // wil be cleared after the transition is complete.
-            IOFSwitch sw = this.activeSwitches.get(dpid);
-            if (sw != null)
-                return sw;
-            return this.syncedSwitches.get(dpid);
-        }
-
-        public void addSwitchEvent(long dpid, String reason, boolean flushNow) {
-            if (flushNow)
-                evSwitch.updateEventWithFlush(new SwitchEvent(dpid, reason));
-            else
-                evSwitch.updateEventNoFlush(new SwitchEvent(dpid, reason));
-        }
-
-    }
-
-
-    /**
-     *  Updates handled by the main loop
-     */
-    interface IUpdate {
-        /**
-         * Calls the appropriate listeners
-         */
-        public void dispatch();
-    }
-
-    /**
-     * Update message that indicates that the controller can now start
-     * flow reconciliation after a SLAVE->MASTER transition
-     */
-    private class ReadyForReconcileUpdate implements IUpdate {
-        @Override
-        public void dispatch() {
-            counters.readyForReconcile.updateCounterWithFlush();
-            if (readyForReconcileListeners != null) {
-                for (IReadyForReconcileListener listener:
-                        readyForReconcileListeners) {
-                    listener.readyForReconcile();
-                }
-            }
-        }
-    }
-
-    enum SwitchUpdateType {
-        ADDED,
-        REMOVED,
-        ACTIVATED,
-        DEACTIVATED,
-        PORTCHANGED,
-        OTHERCHANGE
-    }
-    /**
-     * Update message indicating a switch was added or removed
-     */
-    private class SwitchUpdate implements IUpdate {
-        private final long swId;
-        private final SwitchUpdateType switchUpdateType;
-        private final ImmutablePort port;
-        private final PortChangeType changeType;
-
-
-        public SwitchUpdate(long swId, SwitchUpdateType switchUpdateType) {
-            this(swId, switchUpdateType, null, null);
-        }
-        public SwitchUpdate(long swId,
-                            SwitchUpdateType switchUpdateType,
-                            ImmutablePort port,
-                            PortChangeType changeType) {
-            if (switchUpdateType == SwitchUpdateType.PORTCHANGED) {
-                if (port == null) {
-                    throw new NullPointerException("Port must not be null " +
-                            "for PORTCHANGED updates");
-                }
-                if (changeType == null) {
-                    throw new NullPointerException("ChangeType must not be " +
-                            "null for PORTCHANGED updates");
-                }
-            } else {
-                if (port != null || changeType != null) {
-                    throw new IllegalArgumentException("port and changeType " +
-                            "must be null for " + switchUpdateType +
-                            " updates");
-                }
-            }
-            this.swId = swId;
-            this.switchUpdateType = switchUpdateType;
-            this.port = port;
-            this.changeType = changeType;
-        }
-        @Override
-        public void dispatch() {
-            if (log.isTraceEnabled()) {
-                log.trace("Dispatching switch update {} {}",
-                        HexString.toHexString(swId), switchUpdateType);
-            }
-            if (switchListeners != null) {
-                for (IOFSwitchListener listener : switchListeners) {
-                    switch(switchUpdateType) {
-                        case ADDED:
-                            // don't count here. We have more specific
-                            // counters before the update is created
-                            listener.switchAdded(swId);
-                            break;
-                        case REMOVED:
-                            // don't count here. We have more specific
-                            // counters before the update is created
-                            listener.switchRemoved(swId);
-                            break;
-                        case PORTCHANGED:
-                            counters.switchPortChanged.updateCounterWithFlush();
-                            listener.switchPortChanged(swId, port, changeType);
-                            break;
-                        case ACTIVATED:
-                            // don't count here. We have more specific
-                            // counters before the update is created
-                            listener.switchActivated(swId);
-                            break;
-                        case DEACTIVATED:
-                            // ignore
-                            break;
-                        case OTHERCHANGE:
-                            counters.switchOtherChange.updateCounterWithFlush();
-                            listener.switchChanged(swId);
-                            break;
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Update message indicating controller's role has changed.
-     * RoleManager, which enqueues these updates gurantees that we will
-     * only have a single transition from SLAVE to MASTER.
-     */
-    private class HARoleUpdate implements IUpdate {
-        private final Role newRole;
-        public HARoleUpdate(Role newRole) {
-            if (newRole != Role.MASTER)
-                throw new IllegalArgumentException("Only legal role change is"
-                                                   + "to MASTER. Got to "
-                                                   + newRole);
-            this.newRole = newRole;
-        }
-        @Override
-        public void dispatch() {
-            if (log.isDebugEnabled()) {
-                log.debug("Dispatching HA Role update newRole = {}",
-                          newRole);
-            }
-            for (IHAListener listener : haListeners.getOrderedListeners()) {
-                if (log.isTraceEnabled()) {
-                    log.trace("Calling HAListener {} with transitionToMaster",
-                              listener.getName());
-                }
-                listener.transitionToMaster();
-            }
-            if (newRole != Role.SLAVE) {
-                Controller.this.notifiedRole = newRole;
-            }
-        }
-    }
-
-    /**
-     * Update message indicating
-     * IPs of controllers in controller cluster have changed.
-     */
-    private class HAControllerNodeIPUpdate implements IUpdate {
-        public final Map<String,String> curControllerNodeIPs;
-        public final Map<String,String> addedControllerNodeIPs;
-        public final Map<String,String> removedControllerNodeIPs;
-        public HAControllerNodeIPUpdate(
-                HashMap<String,String> curControllerNodeIPs,
-                HashMap<String,String> addedControllerNodeIPs,
-                HashMap<String,String> removedControllerNodeIPs) {
-            this.curControllerNodeIPs = curControllerNodeIPs;
-            this.addedControllerNodeIPs = addedControllerNodeIPs;
-            this.removedControllerNodeIPs = removedControllerNodeIPs;
-        }
-        @Override
-        public void dispatch() {
-            if (log.isTraceEnabled()) {
-                log.trace("Dispatching HA Controller Node IP update "
-                        + "curIPs = {}, addedIPs = {}, removedIPs = {}",
-                        new Object[] { curControllerNodeIPs, addedControllerNodeIPs,
-                            removedControllerNodeIPs }
-                        );
-            }
-            if (haListeners != null) {
-                for (IHAListener listener: haListeners.getOrderedListeners()) {
-                    listener.controllerNodeIPsChanged(curControllerNodeIPs,
-                            addedControllerNodeIPs, removedControllerNodeIPs);
-                }
-            }
-        }
-    }
-
-    // ***************
-    // Getters/Setters
-    // ***************
-
-    void setStorageSourceService(IStorageSourceService storageSource) {
-        this.storageSource = storageSource;
-    }
-
-    IStorageSourceService getStorageSourceService() {
-        return this.storageSource;
-    }
-
-    void setCounterStore(ICounterStoreService counterStore) {
-        this.counterStore = counterStore;
-    }
-
-    void setDebugCounter(IDebugCounterService debugCounters) {
-        this.debugCounters = debugCounters;
-    }
-
-    public void setDebugEvent(IDebugEventService debugEvent) {
-        this.debugEvents = debugEvent;
-    }
-
-    IDebugCounterService getDebugCounter() {
-        return this.debugCounters;
-    }
-
-    void setSyncService(ISyncService syncService) {
-        this.syncService = syncService;
-    }
-    void setPktInProcessingService(IPktInProcessingTimeService pits) {
-        this.pktinProcTime = pits;
-    }
-
-    void setRestApiService(IRestApiService restApi) {
-        this.restApi = restApi;
-    }
-
-    void setThreadPoolService(IThreadPoolService tp) {
-        this.threadPool = tp;
-    }
-
-    IThreadPoolService getThreadPoolService() {
-        return this.threadPool;
-    }
-
-    @Override
-    public Role getRole() {
-        // FIXME:
-        return notifiedRole;
-    }
-
-    @Override
-    public RoleInfo getRoleInfo() {
-        return roleManager.getRoleInfo();
-    }
-
-    @Override
-    public void setRole(Role role, String roleChangeDescription) {
-        roleManager.setRole(role, roleChangeDescription);
-    }
-
-    // ****************
-    // Message handlers
-    // ****************
-
-    /**
-     * Indicates that ports on the given switch have changed. Enqueue a
-     * switch update.
-     * @param sw
-     */
-     void notifyPortChanged(IOFSwitch sw,
-                            ImmutablePort port,
-                            PortChangeType changeType) {
-         if (sw == null) {
-             String msg = String.format("Switch must not be null. " +
-                     "port=%s, changeType=%s", port, changeType);
-             throw new NullPointerException(msg);
-         }
-         if (port == null) {
-             String msg = String.format("Port must not be null. " +
-                     "switch=%s, changeType=%s", sw, changeType);
-             throw new NullPointerException(msg);
-         }
-         if (changeType == null) {
-             String msg = String.format("ChangeType must not be null. " +
-                     "switch=%s, port=%s", sw, port);
-             throw new NullPointerException(msg);
-         }
-         this.switchManager.switchPortsChanged(sw, port, changeType);
-     }
-
-    /**
-     * flcontext_cache - Keep a thread local stack of contexts
-     */
-    protected static final ThreadLocal<Stack<FloodlightContext>> flcontext_cache =
-        new ThreadLocal <Stack<FloodlightContext>> () {
-            @Override
-            protected Stack<FloodlightContext> initialValue() {
-                return new Stack<FloodlightContext>();
-            }
-        };
-
-    /**
-     * flcontext_alloc - pop a context off the stack, if required create a new one
-     * @return FloodlightContext
-     */
-    protected static FloodlightContext flcontext_alloc() {
-        FloodlightContext flcontext = null;
-
-        if (flcontext_cache.get().empty()) {
-            flcontext = new FloodlightContext();
-        }
-        else {
-            flcontext = flcontext_cache.get().pop();
-        }
-
-        return flcontext;
-    }
-
-    /**
-     * flcontext_free - Free the context to the current thread
-     * @param flcontext
-     */
-    protected void flcontext_free(FloodlightContext flcontext) {
-        flcontext.getStorage().clear();
-        flcontext_cache.get().push(flcontext);
-    }
-
-
-    /**
-     *
-     * Handle and dispatch a message to IOFMessageListeners.
-     *
-     * We only dispatch messages to listeners if the controller's role is MASTER.
-     *
-     * @param sw The switch sending the message
-     * @param m The message the switch sent
-     * @param flContext The floodlight context to use for this message. If
-     * null, a new context will be allocated.
-     * @throws IOException
-     *
-     * FIXME: this method and the ChannelHandler disagree on which messages
-     * should be dispatched and which shouldn't
-     */
-    @LogMessageDocs({
-        @LogMessageDoc(level="ERROR",
-                message="Ignoring PacketIn (Xid = {xid}) because the data" +
-                        " field is empty.",
-                explanation="The switch sent an improperly-formatted PacketIn" +
-                        " message",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="WARN",
-                message="Unhandled OF Message: {} from {}",
-                explanation="The switch sent a message not handled by " +
-                        "the controller")
-    })
-    protected void handleMessage(IOFSwitch sw, OFMessage m,
-                                 FloodlightContext bContext)
-            throws IOException {
-        Ethernet eth = null;
-
-        if (this.notifiedRole == Role.SLAVE) {
-            counters.dispatchMessageWhileSlave.updateCounterNoFlush();
-            // We are SLAVE. Do not dispatch messages to listeners.
-            return;
-        }
-        counters.dispatchMessage.updateCounterNoFlush();
-
-        switch (m.getType()) {
-            case PACKET_IN:
-                OFPacketIn pi = (OFPacketIn)m;
-
-                if (pi.getPacketData().length <= 0) {
-                    log.error("Ignoring PacketIn (Xid = " + pi.getXid() +
-                              ") because the data field is empty.");
-                    return;
-                }
-
-                if (Controller.ALWAYS_DECODE_ETH) {
-                    eth = new Ethernet();
-                    eth.deserialize(pi.getPacketData(), 0,
-                            pi.getPacketData().length);
-                    counterStore.updatePacketInCountersLocal(sw, m, eth);
-                }
-                // fall through to default case...
-
-            default:
-
-                List<IOFMessageListener> listeners = null;
-                if (messageListeners.containsKey(m.getType())) {
-                    listeners = messageListeners.get(m.getType()).
-                            getOrderedListeners();
-                }
-
-                FloodlightContext bc = null;
-                if (listeners != null) {
-                    // Check if floodlight context is passed from the calling
-                    // function, if so use that floodlight context, otherwise
-                    // allocate one
-                    if (bContext == null) {
-                        bc = flcontext_alloc();
-                    } else {
-                        bc = bContext;
-                    }
-                    if (eth != null) {
-                        IFloodlightProviderService.bcStore.put(bc,
-                                IFloodlightProviderService.CONTEXT_PI_PAYLOAD,
-                                eth);
-                    }
-
-                    // Get the starting time (overall and per-component) of
-                    // the processing chain for this packet if performance
-                    // monitoring is turned on
-                    pktinProcTime.recordStartTimePktIn();
-                    Command cmd;
-                    for (IOFMessageListener listener : listeners) {
-                        pktinProcTime.recordStartTimeComp(listener);
-                        cmd = listener.receive(sw, m, bc);
-                        pktinProcTime.recordEndTimeComp(listener);
-
-                        if (Command.STOP.equals(cmd)) {
-                            break;
-                        }
-                    }
-                    pktinProcTime.recordEndTimePktIn(sw, m, bc);
-                } else {
-                    if (m.getType() != OFType.BARRIER_REPLY)
-                        log.warn("Unhandled OF Message: {} from {}", m, sw);
-                    else
-                        log.debug("Received a Barrier Reply, no listeners for it");
-                }
-
-                if ((bContext == null) && (bc != null)) flcontext_free(bc);
-        }
-    }
-
-    void switchActivated(IOFSwitch sw) {
-        this.switchManager.switchActivated(sw);
-    }
-
-    void switchDeactivated(IOFSwitch sw) {
-        this.switchManager.switchDeactivated(sw);
-    }
-
-    void switchDisconnected(IOFSwitch sw) {
-        this.switchManager.switchDisconnected(sw);
-    }
-
-    // ***************
-    // IFloodlightProvider
-    // ***************
-
-    /**
-     * Forward to RoleManager
-     * @param h
-     */
-    void addSwitchChannelAndSendInitialRole(OFChannelHandler h) {
-        roleManager.addOFChannelHandlerAndSendRole(h);
-    }
-
-    /**
-     * Forwards to RoleManager
-     * @param h
-     */
-    void removeSwitchChannel(OFChannelHandler h) {
-        roleManager.removeOFChannelHandler(h);
-    }
-
-    /**
-     * Forwards to RoleManager
-     * @param h
-     * @param role
-     */
-    void reassertRole(OFChannelHandler h, Role role) {
-        roleManager.reassertRole(h, role);
-    }
-
-    // FIXME: remove this method
-    @Override
-    public Map<Long,IOFSwitch> getAllSwitchMap() {
-        return this.switchManager.getAllSwitchMap();
-    }
-
-    @Override
-    public Set<Long> getAllSwitchDpids() {
-        return this.switchManager.getAllSwitchDpids();
-    }
-
-    @Override
-    public IOFSwitch getSwitch(long dpid) {
-        return this.switchManager.getSwitch(dpid);
-    }
-
-    @Override
-    public void addOFSwitchListener(IOFSwitchListener listener) {
-        this.switchListeners.add(listener);
-    }
-
-    @Override
-    public void removeOFSwitchListener(IOFSwitchListener listener) {
-        this.switchListeners.remove(listener);
-    }
-
-    @Override
-    public synchronized void addOFMessageListener(OFType type,
-                                                  IOFMessageListener listener) {
-        ListenerDispatcher<OFType, IOFMessageListener> ldd =
-            messageListeners.get(type);
-        if (ldd == null) {
-            ldd = new ListenerDispatcher<OFType, IOFMessageListener>();
-            messageListeners.put(type, ldd);
-        }
-        ldd.addListener(type, listener);
-    }
-
-    @Override
-    public synchronized void removeOFMessageListener(OFType type,
-                                                     IOFMessageListener listener) {
-        ListenerDispatcher<OFType, IOFMessageListener> ldd =
-            messageListeners.get(type);
-        if (ldd != null) {
-            ldd.removeListener(listener);
-        }
-    }
-
-    private void logListeners() {
-        for (Map.Entry<OFType,
-                       ListenerDispatcher<OFType,
-                                          IOFMessageListener>> entry
-             : messageListeners.entrySet()) {
-
-            OFType type = entry.getKey();
-            ListenerDispatcher<OFType, IOFMessageListener> ldd =
-                    entry.getValue();
-
-            StringBuilder sb = new StringBuilder();
-            sb.append("OFListeners for ");
-            sb.append(type);
-            sb.append(": ");
-            for (IOFMessageListener l : ldd.getOrderedListeners()) {
-                sb.append(l.getName());
-                sb.append(",");
-            }
-            log.debug(sb.toString());
-        }
-
-        StringBuilder sb = new StringBuilder();
-        sb.append("HAListeners: ");
-        for (IHAListener l: haListeners.getOrderedListeners()) {
-            sb.append(l.getName());
-            sb.append(", ");
-        }
-        log.debug(sb.toString());
-    }
-
-    public void removeOFMessageListeners(OFType type) {
-        messageListeners.remove(type);
-    }
-
-    @Override
-    public Map<OFType, List<IOFMessageListener>> getListeners() {
-        Map<OFType, List<IOFMessageListener>> lers =
-            new HashMap<OFType, List<IOFMessageListener>>();
-        for(Entry<OFType, ListenerDispatcher<OFType, IOFMessageListener>> e :
-            messageListeners.entrySet()) {
-            lers.put(e.getKey(), e.getValue().getOrderedListeners());
-        }
-        return Collections.unmodifiableMap(lers);
-    }
-
-    @Override
-    @LogMessageDocs({
-        @LogMessageDoc(level="ERROR",
-                message="Error reinjecting OFMessage on switch {switch}",
-                explanation="An I/O error occured while attempting to " +
-                        "process an OpenFlow message",
-                recommendation=LogMessageDoc.CHECK_SWITCH)
-    })
-    public boolean injectOfMessage(IOFSwitch sw, OFMessage msg,
-                                   FloodlightContext bc) {
-        if (sw == null)
-            throw new NullPointerException("Switch must not be null");
-        if (msg == null)
-            throw new NullPointerException("OFMessage must not be null");
-
-        // FIXME: Do we need to be able to inject messages from switches
-        // where we're the slave controller (i.e. they're connected but
-        // not active)?
-        if (!sw.isActive()) return false;
-
-        try {
-            // Pass Floodlight context to the handleMessages()
-            handleMessage(sw, msg, bc);
-        } catch (IOException e) {
-            log.error("Error reinjecting OFMessage on switch {}",
-                      sw.getStringId());
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    @LogMessageDoc(message="Calling System.exit",
-                   explanation="The controller is terminating")
-    public synchronized void terminate() {
-        log.info("Calling System.exit");
-        System.exit(1);
-    }
-
-    @Override
-    public boolean injectOfMessage(IOFSwitch sw, OFMessage msg) {
-        // call the overloaded version with floodlight context set to null
-        return injectOfMessage(sw, msg, null);
-    }
-
-    @Override
-    public void handleOutgoingMessage(IOFSwitch sw, OFMessage m,
-                                      FloodlightContext bc) {
-        if (sw == null)
-            throw new NullPointerException("Switch must not be null");
-        if (m == null)
-            throw new NullPointerException("OFMessage must not be null");
-        if (bc == null)
-            bc = new FloodlightContext();
-        if (log.isTraceEnabled()) {
-            String str = OFMessage.getDataAsString(sw, m, bc);
-            log.trace("{}", str);
-        }
-
-        List<IOFMessageListener> listeners = null;
-        if (messageListeners.containsKey(m.getType())) {
-            listeners =
-                    messageListeners.get(m.getType()).getOrderedListeners();
-        }
-
-        if (listeners != null) {
-            for (IOFMessageListener listener : listeners) {
-                if (Command.STOP.equals(listener.receive(sw, m, bc))) {
-                    break;
-                }
-            }
-        }
-    }
-
-    @Override
-    public BasicFactory getOFMessageFactory() {
-        return factory;
-    }
-
-    // **************
-    // Initialization
-    // **************
-
-
-    /**
-     * Sets the initial role based on properties in the config params.
-     * It looks for two different properties.
-     * If the "role" property is specified then the value should be
-     * either "EQUAL", "MASTER", or "SLAVE" and the role of the
-     * controller is set to the specified value. If the "role" property
-     * is not specified then it looks next for the "role.path" property.
-     * In this case the value should be the path to a property file in
-     * the file system that contains a property called "floodlight.role"
-     * which can be one of the values listed above for the "role" property.
-     * The idea behind the "role.path" mechanism is that you have some
-     * separate heartbeat and master controller election algorithm that
-     * determines the role of the controller. When a role transition happens,
-     * it updates the current role in the file specified by the "role.path"
-     * file. Then if floodlight restarts for some reason it can get the
-     * correct current role of the controller from the file.
-     * @param configParams The config params for the FloodlightProvider service
-     * @return A valid role if role information is specified in the
-     *         config params, otherwise null
-     */
-    @LogMessageDocs({
-        @LogMessageDoc(message="Controller role set to {role}",
-                explanation="Setting the initial HA role to "),
-        @LogMessageDoc(level="ERROR",
-                message="Invalid current role value: {role}",
-                explanation="An invalid HA role value was read from the " +
-                            "properties file",
-                recommendation=LogMessageDoc.CHECK_CONTROLLER)
-    })
-    protected Role getInitialRole(Map<String, String> configParams) {
-        Role role = Role.MASTER;
-        String roleString = configParams.get("role");
-        if (roleString == null) {
-            String rolePath = configParams.get("rolepath");
-            if (rolePath != null) {
-                Properties properties = new Properties();
-                try {
-                    properties.load(new FileInputStream(rolePath));
-                    roleString = properties.getProperty("floodlight.role");
-                }
-                catch (IOException exc) {
-                    // Don't treat it as an error if the file specified by the
-                    // rolepath property doesn't exist. This lets us enable the
-                    // HA mechanism by just creating/setting the floodlight.role
-                    // property in that file without having to modify the
-                    // floodlight properties.
-                }
-            }
-        }
-
-        if (roleString != null) {
-            // Canonicalize the string to the form used for the enum constants
-            roleString = roleString.trim().toUpperCase();
-            try {
-                role = Role.valueOf(roleString);
-            }
-            catch (IllegalArgumentException exc) {
-                log.error("Invalid current role value: {}", roleString);
-            }
-        }
-        if (role == Role.EQUAL)
-            role = Role.MASTER;
-
-        log.info("Controller role set to {}", role);
-
-        return role;
-    }
-
-    /**
-     * Tell controller that we're ready to accept switches loop
-     * @throws IOException
-     */
-    @Override
-    @LogMessageDocs({
-        @LogMessageDoc(message="Listening for switch connections on {address}",
-                explanation="The controller is ready and listening for new" +
-                        " switch connections"),
-        @LogMessageDoc(message="Storage exception in controller " +
-                        "updates loop; terminating process",
-                explanation=ERROR_DATABASE,
-                recommendation=LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level="ERROR",
-                message="Exception in controller updates loop",
-                explanation="Failed to dispatch controller event",
-                recommendation=LogMessageDoc.GENERIC_ACTION)
-    })
-    public void run() {
-        if (log.isDebugEnabled()) {
-            logListeners();
-        }
-
-        try {
-           final ServerBootstrap bootstrap = createServerBootStrap();
-
-            bootstrap.setOption("reuseAddr", true);
-            bootstrap.setOption("child.keepAlive", true);
-            bootstrap.setOption("child.tcpNoDelay", true);
-            bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
-
-            ChannelPipelineFactory pfact =
-                    new OpenflowPipelineFactory(this, null);
-            bootstrap.setPipelineFactory(pfact);
-            InetSocketAddress sa =
-            		(openFlowHost == null)
-            		? new InetSocketAddress(openFlowPort)
-            		: new InetSocketAddress(openFlowHost, openFlowPort);
-            final ChannelGroup cg = new DefaultChannelGroup();
-            cg.add(bootstrap.bind(sa));
-
-            log.info("Listening for switch connections on {}", sa);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-
-        // main loop
-        while (true) {
-            try {
-                IUpdate update = updates.take();
-                update.dispatch();
-            } catch (InterruptedException e) {
-                log.error("Received interrupted exception in updates loop;" +
-                          "terminating process");
-                terminate();
-            } catch (StorageException e) {
-                log.error("Storage exception in controller " +
-                          "updates loop; terminating process", e);
-                terminate();
-            } catch (Exception e) {
-                log.error("Exception in controller updates loop", e);
-            }
-        }
-    }
-
-    private ServerBootstrap createServerBootStrap() {
-        if (workerThreads == 0) {
-            return new ServerBootstrap(
-                    new NioServerSocketChannelFactory(
-                            Executors.newCachedThreadPool(),
-                            Executors.newCachedThreadPool()));
-        } else {
-            return new ServerBootstrap(
-                    new NioServerSocketChannelFactory(
-                            Executors.newCachedThreadPool(),
-                            Executors.newCachedThreadPool(), workerThreads));
-        }
-    }
-
-    private void setConfigParams(Map<String, String> configParams) {
-        String ofPort = configParams.get("openflowport");
-        if (ofPort != null) {
-            this.openFlowPort = Integer.parseInt(ofPort);
-        }
-        log.debug("OpenFlow port set to {}", this.openFlowPort);
-        String threads = configParams.get("workerthreads");
-        if (threads != null) {
-            this.workerThreads = Integer.parseInt(threads);
-        }
-        log.debug("Number of worker threads set to {}", this.workerThreads);
-
-    }
-
-    private void initVendorMessages() {
-        // Configure openflowj to be able to parse the role request/reply
-        // vendor messages.
-        OFNiciraVendorExtensions.initialize();
-
-        // Register the standard Vendor actions that we support
-        OFVendorActions.registerStandardVendorActions();
-    }
-
-    /**
-     * Initialize internal data structures
-     */
-    public void init(Map<String, String> configParams) {
-        // These data structures are initialized here because other
-        // module's startUp() might be called before ours
-        this.messageListeners =
-                new ConcurrentHashMap<OFType,
-                                      ListenerDispatcher<OFType,
-                                                         IOFMessageListener>>();
-        this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>();
-        // add switch notification listener
-        this.addOFSwitchListener(new NotificationSwitchListener());
-        this.readyForReconcileListeners =
-                new CopyOnWriteArraySet<IReadyForReconcileListener>();
-        this.haListeners =
-                new ListenerDispatcher<HAListenerTypeMarker, IHAListener>();
-        this.driverRegistry = new NaiiveSwitchDriverRegistry();
-        this.controllerNodeIPsCache = new HashMap<String, String>();
-        this.updates = new LinkedBlockingQueue<IUpdate>();
-        this.factory = BasicFactory.getInstance();
-        this.providerMap = new HashMap<String, List<IInfoProvider>>();
-        setConfigParams(configParams);
-        Role initialRole = getInitialRole(configParams);
-        this.notifiedRole = initialRole;
-        initVendorMessages();
-
-        String option = configParams.get("flushSwitchesOnReconnect");
-
-        if (option != null && option.equalsIgnoreCase("true")) {
-            this.setAlwaysClearFlowsOnSwActivate(true);
-            log.info("Flush switches on reconnect -- Enabled.");
-        } else {
-            this.setAlwaysClearFlowsOnSwActivate(false);
-            log.info("Flush switches on reconnect -- Disabled");
-        }
-
-        uplinkPortPrefixSet = new HashSet<String>();
-        uplinkPortPrefixSet.add("eth");
-        uplinkPortPrefixSet.add("bond");
-        String str = configParams.get("uplinkPortPrefix");
-        if (str != null) {
-            List<String> items = Arrays.asList(str.split("\\s*,\\s*"));
-            if (items != null) {
-                for (String s: items) {
-                    if (s.length() > 0) {
-                        uplinkPortPrefixSet.add(s);
-                    }
-                }
-            }
-        }
-
-        this.roleManager = new RoleManager(this.notifiedRole,
-                                           INITIAL_ROLE_CHANGE_DESCRIPTION);
-        this.switchManager = new SwitchManager(this.notifiedRole);
-        this.counters = new Counters();
-        this.swConnectCache =
-                new TimedCache<Long>(100, 5*1000 );  // 5 seconds interval
-     }
-
-    /**
-     * Startup all of the controller's components
-     */
-    @LogMessageDoc(message="Waiting for storage source",
-                explanation="The system database is not yet ready",
-                recommendation="If this message persists, this indicates " +
-                        "that the system database has failed to start. " +
-                        LogMessageDoc.CHECK_CONTROLLER)
-    public void startupComponents() throws FloodlightModuleException {
-        // Create the table names we use
-        storageSource.createTable(CONTROLLER_TABLE_NAME, null);
-        storageSource.createTable(CONTROLLER_INTERFACE_TABLE_NAME, null);
-        storageSource.createTable(SWITCH_CONFIG_TABLE_NAME, null);
-        storageSource.setTablePrimaryKeyName(CONTROLLER_TABLE_NAME,
-                                             CONTROLLER_ID);
-        storageSource.addListener(CONTROLLER_INTERFACE_TABLE_NAME, this);
-
-        storageSource.createTable(FLOW_PRIORITY_TABLE_NAME, null);
-        storageSource.setTablePrimaryKeyName(FLOW_PRIORITY_TABLE_NAME,
-                                             FLOW_COLUMN_PRIMARY_KEY);
-        storageSource.addListener(FLOW_PRIORITY_TABLE_NAME, this);
-        readFlowPriorityConfigurationFromStorage();
-
-        // Startup load monitoring
-        if (overload_drop) {
-            this.loadmonitor.startMonitoring(
-                this.threadPool.getScheduledExecutor());
-        }
-
-        // Add our REST API
-        restApi.addRestletRoutable(new CoreWebRoutable());
-
-        this.ses = threadPool.getScheduledExecutor();
-
-        try {
-            this.syncService.registerStore(SWITCH_SYNC_STORE_NAME, Scope.LOCAL);
-            this.storeClient = this.syncService
-                    .getStoreClient(SWITCH_SYNC_STORE_NAME,
-                                    Long.class,
-                                    SwitchSyncRepresentation.class);
-            this.storeClient.addStoreListener(this.switchManager);
-        } catch (SyncException e) {
-            throw new FloodlightModuleException("Error while setting up sync service", e);
-        }
-
-        try {
-            this.counters.createCounters(debugCounters);
-        } catch (CounterException e) {
-            throw new FloodlightModuleException(e.getMessage());
-        }
-
-        addInfoProvider("summary", this);
-
-        registerControllerDebugEvents();
-    }
-
-    @LogMessageDoc(level="ERROR",
-            message="failed to access storage: {reason}",
-            explanation="Could not retrieve forwarding configuration",
-            recommendation=LogMessageDoc.CHECK_CONTROLLER)
-    private void readFlowPriorityConfigurationFromStorage() {
-        try {
-            Map<String, Object> row;
-            IResultSet resultSet = storageSource.executeQuery(
-                FLOW_PRIORITY_TABLE_NAME, FLOW_COLUMN_NAMES, null, null);
-            if (resultSet == null)
-                return;
-
-            for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) {
-                row = it.next().getRow();
-                if (row.containsKey(FLOW_COLUMN_PRIMARY_KEY)) {
-                    String primary_key = (String) row.get(FLOW_COLUMN_PRIMARY_KEY);
-                    if (primary_key.equals(FLOW_VALUE_PRIMARY_KEY)) {
-                        if (row.containsKey(FLOW_COLUMN_ACCESS_PRIORITY)) {
-                            accessPriority =
-                                Short.valueOf((String) row.get(FLOW_COLUMN_ACCESS_PRIORITY));
-                        }
-                        if (row.containsKey(FLOW_COLUMN_CORE_PRIORITY)) {
-                            corePriority =
-                                    Short.valueOf((String) row.get(FLOW_COLUMN_CORE_PRIORITY));
-                        }
-                    }
-                }
-            }
-        }
-        catch (StorageException e) {
-            log.error("Failed to access storage for forwarding configuration: {}",
-                      e.getMessage());
-        }
-        catch (NumberFormatException e) {
-            // log error, no stack-trace
-            log.error("Failed to read core or access flow priority from " +
-                      "storage. Illegal number: {}", e.getMessage());
-        }
-    }
-
-
-    private void registerControllerDebugEvents() throws FloodlightModuleException {
-        if (debugEvents == null) {
-            debugEvents = new NullDebugEvent();
-        }
-        try {
-            evSwitch = debugEvents.registerEvent(
-                               Counters.prefix, "switchevent",
-                               "Switch connected, disconnected or port changed",
-                               EventType.ALWAYS_LOG, SwitchEvent.class, 100);
-        } catch (MaxEventsRegistered e) {
-            throw new FloodlightModuleException("Max events registered", e);
-        }
-    }
-
-    public class SwitchEvent {
-        @EventColumn(name = "dpid", description = EventFieldType.DPID)
-        long dpid;
-
-        @EventColumn(name = "reason", description = EventFieldType.STRING)
-        String reason;
-
-        public SwitchEvent(long dpid, String reason) {
-            this.dpid = dpid;
-            this.reason = reason;
-        }
-    }
-
-    @Override
-    public void addInfoProvider(String type, IInfoProvider provider) {
-        if (!providerMap.containsKey(type)) {
-            providerMap.put(type, new ArrayList<IInfoProvider>());
-        }
-        providerMap.get(type).add(provider);
-    }
-
-    @Override
-    public void removeInfoProvider(String type, IInfoProvider provider) {
-        if (!providerMap.containsKey(type)) {
-            log.debug("Provider type {} doesn't exist.", type);
-            return;
-        }
-
-        providerMap.get(type).remove(provider);
-    }
-
-    @Override
-    public Map<String, Object> getControllerInfo(String type) {
-        if (!providerMap.containsKey(type)) return null;
-
-        Map<String, Object> result = new LinkedHashMap<String, Object>();
-        for (IInfoProvider provider : providerMap.get(type)) {
-            result.putAll(provider.getInfo(type));
-        }
-
-        return result;
-    }
-
-    @Override
-    public void addHAListener(IHAListener listener) {
-        this.haListeners.addListener(null,listener);
-    }
-
-    @Override
-    public void removeHAListener(IHAListener listener) {
-        this.haListeners.removeListener(listener);
-    }
-
-    @Override
-    public void addReadyForReconcileListener(IReadyForReconcileListener l) {
-        this.readyForReconcileListeners.add(l);
-    }
-
-
-    /**
-     * Handle changes to the controller nodes IPs and dispatch update.
-     */
-    protected void handleControllerNodeIPChanges() {
-        HashMap<String,String> curControllerNodeIPs = new HashMap<String,String>();
-        HashMap<String,String> addedControllerNodeIPs = new HashMap<String,String>();
-        HashMap<String,String> removedControllerNodeIPs =new HashMap<String,String>();
-        String[] colNames = { CONTROLLER_INTERFACE_CONTROLLER_ID,
-                           CONTROLLER_INTERFACE_TYPE,
-                           CONTROLLER_INTERFACE_NUMBER,
-                           CONTROLLER_INTERFACE_DISCOVERED_IP };
-        synchronized(controllerNodeIPsCache) {
-            // We currently assume that interface Ethernet0 is the relevant
-            // controller interface. Might change.
-            // We could (should?) implement this using
-            // predicates, but creating the individual and compound predicate
-            // seems more overhead then just checking every row. Particularly,
-            // since the number of rows is small and changes infrequent
-            IResultSet res = storageSource.executeQuery(CONTROLLER_INTERFACE_TABLE_NAME,
-                    colNames,null, null);
-            while (res.next()) {
-                if (res.getString(CONTROLLER_INTERFACE_TYPE).equals("Ethernet") &&
-                        res.getInt(CONTROLLER_INTERFACE_NUMBER) == 0) {
-                    String controllerID = res.getString(CONTROLLER_INTERFACE_CONTROLLER_ID);
-                    String discoveredIP = res.getString(CONTROLLER_INTERFACE_DISCOVERED_IP);
-                    String curIP = controllerNodeIPsCache.get(controllerID);
-
-                    curControllerNodeIPs.put(controllerID, discoveredIP);
-                    if (curIP == null) {
-                        // new controller node IP
-                        addedControllerNodeIPs.put(controllerID, discoveredIP);
-                    }
-                    else if (!curIP.equals(discoveredIP)) {
-                        // IP changed
-                        removedControllerNodeIPs.put(controllerID, curIP);
-                        addedControllerNodeIPs.put(controllerID, discoveredIP);
-                    }
-                }
-            }
-            // Now figure out if rows have been deleted. We can't use the
-            // rowKeys from rowsDeleted directly, since the tables primary
-            // key is a compound that we can't disassemble
-            Set<String> curEntries = curControllerNodeIPs.keySet();
-            Set<String> removedEntries = controllerNodeIPsCache.keySet();
-            removedEntries.removeAll(curEntries);
-            for (String removedControllerID : removedEntries)
-                removedControllerNodeIPs.put(removedControllerID,
-                                             controllerNodeIPsCache.get(removedControllerID));
-            controllerNodeIPsCache.clear();
-            controllerNodeIPsCache.putAll(curControllerNodeIPs);
-            counters.controllerNodeIpsChanged.updateCounterWithFlush();
-            HAControllerNodeIPUpdate update = new HAControllerNodeIPUpdate(
-                                curControllerNodeIPs, addedControllerNodeIPs,
-                                removedControllerNodeIPs);
-            if (!removedControllerNodeIPs.isEmpty() || !addedControllerNodeIPs.isEmpty()) {
-                addUpdateToQueue(update);
-            }
-        }
-    }
-
-    @Override
-    public Map<String, String> getControllerNodeIPs() {
-        // We return a copy of the mapping so we can guarantee that
-        // the mapping return is the same as one that will be (or was)
-        // dispatched to IHAListeners
-        HashMap<String,String> retval = new HashMap<String,String>();
-        synchronized(controllerNodeIPsCache) {
-            retval.putAll(controllerNodeIPsCache);
-        }
-        return retval;
-    }
-
-    private static final String FLOW_PRIORITY_CHANGED_AFTER_STARTUP =
-            "Flow priority configuration has changed after " +
-            "controller startup. Restart controller for new " +
-            "configuration to take effect.";
-    @LogMessageDoc(level="WARN",
-            message=FLOW_PRIORITY_CHANGED_AFTER_STARTUP,
-            explanation="A user has changed the priority with which access " +
-                    "and core flows are installed after controller startup. " +
-                    "Changing this setting will only take affect after a " +
-                    "controller restart",
-            recommendation="Restart controller")
-    @Override
-    public void rowsModified(String tableName, Set<Object> rowKeys) {
-        if (tableName.equals(CONTROLLER_INTERFACE_TABLE_NAME)) {
-            handleControllerNodeIPChanges();
-        } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) {
-            log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP);
-        }
-
-
-    }
-
-    @Override
-    public void rowsDeleted(String tableName, Set<Object> rowKeys) {
-        if (tableName.equals(CONTROLLER_INTERFACE_TABLE_NAME)) {
-            handleControllerNodeIPChanges();
-        } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) {
-            log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP);
-        }
-    }
-
-    @Override
-    public long getSystemStartTime() {
-        RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
-        return rb.getStartTime();
-    }
-
-    @Override
-    public void setAlwaysClearFlowsOnSwActivate(boolean value) {
-        this.alwaysClearFlowsOnSwActivate = value;
-    }
-
-
-    @Override
-    public Map<String, Long> getMemory() {
-        Map<String, Long> m = new HashMap<String, Long>();
-        Runtime runtime = Runtime.getRuntime();
-        m.put("total", runtime.totalMemory());
-        m.put("free", runtime.freeMemory());
-        return m;
-    }
-
-    @Override
-    public Long getUptime() {
-        RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
-        return rb.getUptime();
-    }
-
-
-
-    @Override
-    public void addOFSwitchDriver(String manufacturerDescriptionPrefix,
-                                  IOFSwitchDriver driver) {
-        driverRegistry.addSwitchDriver(manufacturerDescriptionPrefix, driver);
-    }
-
-    /**
-     * Forward to the registry to get an IOFSwitch instance.
-     * @param desc
-     * @return
-     */
-    IOFSwitch getOFSwitchInstance(OFDescriptionStatistics desc) {
-        return driverRegistry.getOFSwitchInstance(desc);
-    }
-
-    /**
-     *  Switch Added/Deleted Events
-     */
-    @Override
-    public void addSwitchEvent(long switchDPID, String reason, boolean flushNow) {
-        switchManager.addSwitchEvent(switchDPID, reason, flushNow);
-    }
-
-    @LogMessageDoc(level="WARN",
-            message="Failure adding update {} to queue",
-            explanation="The controller tried to add an internal notification" +
-                        " to its message queue but the add failed.",
-            recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
-    private void addUpdateToQueue(IUpdate update) {
-        try {
-            this.updates.put(update);
-        } catch (InterruptedException e) {
-            // This should never happen
-            log.error("Failure adding update {} to queue.", update);
-        }
-    }
-
-    void flushAll() {
-        // Flush all flow-mods/packet-out/stats generated from this "train"
-        OFSwitchBase.flush_all();
-        counterStore.updateFlush();
-        debugCounters.flushCounters();
-        debugEvents.flushEvents();
-    }
-
-    short getAccessFlowPriority() {
-        return accessPriority;
-    }
-
-    short getCoreFlowPriority() {
-        return corePriority;
-    }
-
-    /**
-     * FOR TESTING ONLY.
-     * Dispatch all updates in the update queue until queue is empty
-     */
-    void processUpdateQueueForTesting() {
-        while(!updates.isEmpty()) {
-            IUpdate update = updates.poll();
-            if (update != null)
-                update.dispatch();
-        }
-    }
-
-    /**
-     * FOR TESTING ONLY
-     * check if update queue is empty
-     */
-    boolean isUpdateQueueEmptyForTesting() {
-        return this.updates.isEmpty();
-    }
-
-    /**
-     * FOR TESTING ONLY
-     * @param update
-     */
-    void setConsolidateStoreTaskDelay(int consolidateStoreTaskDelayMs) {
-        this.consolidateStoreTimeDelayMs = consolidateStoreTaskDelayMs;
-    }
-
-    /**
-     * FOR TESTING ONLY
-     * returns the store listener so we can send events to the listener
-     */
-    IStoreListener<Long> getStoreListener() {
-        return this.switchManager;
-    }
-
-    @Override
-    public Map<String, Object> getInfo(String type) {
-        if (!"summary".equals(type)) return null;
-
-        Map<String, Object> info = new HashMap<String, Object>();
-
-        info.put("# Switches", this.getAllSwitchDpids().size());
-        return info;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java
new file mode 100644
index 000000000..c511a09ee
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/ControllerCounters.java
@@ -0,0 +1,48 @@
+package net.floodlightcontroller.core.internal;
+
+import net.floodlightcontroller.core.IOFSwitchBackend;
+import net.floodlightcontroller.core.OFConnectionCounters;
+import net.floodlightcontroller.debugcounter.IDebugCounter;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+@SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD",
+                    justification = "It is ok to predefine Debug Counters that are not yet used")
+public class ControllerCounters {
+
+    public final String prefix = ControllerCounters.class.getSimpleName();
+    public final String statsPrefix = IOFSwitchBackend.class.getPackage()
+                                                            .getName();
+
+    public final IDebugCounter packetParsingError;
+    public final IDebugCounter dispatchMessageWhileStandby;
+    public final IDebugCounter dispatchMessage;
+
+    public ControllerCounters(IDebugCounterService debugCounters) {
+        debugCounters.registerModule(prefix);
+        debugCounters.registerModule(OFConnectionCounters.COUNTER_MODULE);
+
+        dispatchMessageWhileStandby = debugCounters.registerCounter(prefix,
+                                                                    "dispatch-message-while-slave",
+                                                                    "Number of times an OF message was received "
+                                                                            + "and supposed to be dispatched but the "
+                                                                            + "controller was in SLAVE role and the message "
+                                                                            + "was not dispatched");
+        // does this cnt make sense? more specific?? per type?
+        // count stops?
+        dispatchMessage = debugCounters.registerCounter(prefix,
+                                                        "dispatch-message",
+                                                        "Number of times an OF message was dispatched "
+                                                                + "to registered modules");
+
+        // TODO: FIXME
+        // Need a better way to handle these
+        packetParsingError = debugCounters.registerCounter(prefix,
+                                                           "packet-parsing-error",
+                                                           "Number of times the packet parsing "
+                                                                   + "encountered an error",
+                                                           MetaData.ERROR);
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/FloodlightProvider.java b/src/main/java/net/floodlightcontroller/core/internal/FloodlightProvider.java
index 8299bb2c2..12716c4ba 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/FloodlightProvider.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/FloodlightProvider.java
@@ -21,6 +21,11 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
+import net.floodlightcontroller.core.internal.IOFSwitchService;
+import net.floodlightcontroller.core.internal.Controller;
+import net.floodlightcontroller.core.module.Run;
+
+import org.projectfloodlight.openflow.protocol.OFType;
 import org.sdnplatform.sync.ISyncService;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
@@ -39,6 +44,10 @@ import net.floodlightcontroller.threadpool.IThreadPoolService;
 public class FloodlightProvider implements IFloodlightModule {
     Controller controller;
 
+    public FloodlightProvider() {
+        controller = new Controller();
+    }
+    
     @Override
     public Collection<Class<? extends IFloodlightService>> getModuleServices() {
         Collection<Class<? extends IFloodlightService>> services =
@@ -70,6 +79,7 @@ public class FloodlightProvider implements IFloodlightModule {
         dependencies.add(ICounterStoreService.class);
         dependencies.add(IDebugCounterService.class);
         dependencies.add(IDebugEventService.class);
+        dependencies.add(IOFSwitchService.class);
         dependencies.add(IThreadPoolService.class);
         dependencies.add(ISyncService.class);
         return dependencies;
@@ -99,6 +109,23 @@ public class FloodlightProvider implements IFloodlightModule {
     @Override
     public void startUp(FloodlightModuleContext context)
             throws FloodlightModuleException {
-        controller.startupComponents();
+        controller.startupComponents(context.getModuleLoader());
     }
+    
+    @Run(mainLoop=true)
+    public void run() throws FloodlightModuleException {
+        controller.run();
+    }
+
+	@Override
+	public boolean isCallbackOrderingPrereq(OFType type, String name) {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	@Override
+	public boolean isCallbackOrderingPostreq(OFType type, String name) {
+		// TODO Auto-generated method stub
+		return false;
+	}
 }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java b/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java
index e89b3895c..89ef68109 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutHandler.java
@@ -1,7 +1,7 @@
 /**
-*    Copyright 2011, Big Switch Networks, Inc. 
+*    Copyright 2011, Big Switch Networks, Inc.
 *    Originally created by David Erickson, Stanford University
-* 
+*
 *    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
@@ -30,36 +30,37 @@ import org.jboss.netty.util.TimerTask;
 /**
  * Trigger a timeout if a switch fails to complete handshake soon enough
  */
-public class HandshakeTimeoutHandler 
+public class HandshakeTimeoutHandler
     extends SimpleChannelUpstreamHandler {
-    static final HandshakeTimeoutException EXCEPTION = 
+
+    static final HandshakeTimeoutException EXCEPTION =
             new HandshakeTimeoutException();
-    
-    final OFChannelHandler channelHandler;
+
+    final OFChannelHandler handshakeHandler;
     final Timer timer;
     final long timeoutNanos;
     volatile Timeout timeout;
-    
-    public HandshakeTimeoutHandler(OFChannelHandler channelHandler,
+
+    public HandshakeTimeoutHandler(OFChannelHandler handshakeHandler,
                                    Timer timer,
                                    long timeoutSeconds) {
         super();
-        this.channelHandler = channelHandler;
+        this.handshakeHandler = handshakeHandler;
         this.timer = timer;
         this.timeoutNanos = TimeUnit.SECONDS.toNanos(timeoutSeconds);
 
     }
-    
+
     @Override
     public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
             throws Exception {
         if (timeoutNanos > 0) {
-            timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx), 
+            timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx),
                                        timeoutNanos, TimeUnit.NANOSECONDS);
         }
         ctx.sendUpstream(e);
     }
-    
+
     @Override
     public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
             throws Exception {
@@ -68,7 +69,7 @@ public class HandshakeTimeoutHandler
             timeout = null;
         }
     }
-    
+
     private final class HandshakeTimeoutTask implements TimerTask {
 
         private final ChannelHandlerContext ctx;
@@ -86,7 +87,7 @@ public class HandshakeTimeoutHandler
             if (!ctx.getChannel().isOpen()) {
                 return;
             }
-            if (!channelHandler.isHandshakeComplete())
+            if (!handshakeHandler.isSwitchHandshakeComplete())
                 Channels.fireExceptionCaught(ctx, EXCEPTION);
         }
     }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/IAppHandshakePluginFactory.java b/src/main/java/net/floodlightcontroller/core/internal/IAppHandshakePluginFactory.java
new file mode 100644
index 000000000..fd45309f3
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/IAppHandshakePluginFactory.java
@@ -0,0 +1,19 @@
+package net.floodlightcontroller.core.internal;
+
+/**
+ * This interface creates a contract used by the switch handshake handler. Each
+ * switch that is connected needs it's own running instance of the registered
+ * plugins. Thus is depends on a factory to churn out these instances.
+ * @author Jason Parraga <Jason.Parraga@bigswitch.com>
+ *
+ */
+public interface IAppHandshakePluginFactory {
+
+    /**
+     * Create an instance of OFSwitchAppHandshakePlugin
+     * @return an instance of OFSwitchAppHandshakePlugin
+     */
+    OFSwitchAppHandshakePlugin createPlugin();
+}
+
+
diff --git a/src/main/java/net/floodlightcontroller/core/internal/INewOFConnectionListener.java b/src/main/java/net/floodlightcontroller/core/internal/INewOFConnectionListener.java
new file mode 100644
index 000000000..9f03bc38e
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/INewOFConnectionListener.java
@@ -0,0 +1,19 @@
+package net.floodlightcontroller.core.internal;
+
+import net.floodlightcontroller.core.IOFConnectionBackend;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+
+/** a listener that is notified when a new OFConnection has been opened and
+ *  handshaked (i.e., the {@link OFFeaturesReply} has been received.
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public interface INewOFConnectionListener {
+    /** notify this listener that a new connection has been opened
+     *
+     * @param connection - the new connection
+     * @param featuresReply - the {@link OFFeaturesReply} that was received.
+     */
+    void connectionOpened(IOFConnectionBackend connection,
+                          OFFeaturesReply featuresReply);
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/IOFConnectionListener.java b/src/main/java/net/floodlightcontroller/core/internal/IOFConnectionListener.java
new file mode 100644
index 000000000..f537e2d4f
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/IOFConnectionListener.java
@@ -0,0 +1,12 @@
+package net.floodlightcontroller.core.internal;
+
+import net.floodlightcontroller.core.IOFConnectionBackend;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+public interface IOFConnectionListener {
+    void connectionClosed(IOFConnectionBackend connection);
+
+    void messageReceived(IOFConnectionBackend connection, OFMessage m);
+
+    boolean isSwitchHandshakeComplete(IOFConnectionBackend connection);
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java
new file mode 100644
index 000000000..81a85346c
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchManager.java
@@ -0,0 +1,124 @@
+package net.floodlightcontroller.core.internal;
+
+import java.util.List;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IOFConnectionBackend;
+import net.floodlightcontroller.core.IOFSwitch.SwitchStatus;
+import net.floodlightcontroller.core.IOFSwitchBackend;
+import net.floodlightcontroller.core.IOFSwitchDriver;
+import net.floodlightcontroller.core.LogicalOFMessageCategory;
+import net.floodlightcontroller.core.PortChangeType;
+import net.floodlightcontroller.core.SwitchDescription;
+
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.types.DatapathId;
+
+import com.google.common.collect.ImmutableList;
+
+public interface IOFSwitchManager {
+
+    /**
+     * Called when a switch is added.
+     * @param sw the added switch
+     */
+    void switchAdded(IOFSwitchBackend sw);
+
+    /**
+     * Called when a switch disconnects
+     * @param sw the added switch
+     */
+    void switchDisconnected(IOFSwitchBackend sw);
+
+    /**
+     * Indicates that ports on the given switch have changed. Enqueue a
+     * switch update.
+     * @param sw the added switch
+     */
+    void notifyPortChanged(IOFSwitchBackend sw, OFPortDesc port,
+                           PortChangeType type);
+
+    /**
+     * Relays to ISwitchDriverRegistry
+     */
+    IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection,
+                                         SwitchDescription description,
+                                         OFFactory factory,
+                                         DatapathId datapathId);
+
+    /**
+     * Relays an upstream message to the controller to dispatch to listeners.
+     * @param sw The switch the message was received on.
+     * @param m The message received.
+     * @param bContext the Floodlight context of the message, normally null in this case.
+     */
+    void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext);
+
+    /**
+     * Gets an unmodifiable collection of OFSwitchHandshakeHandlers
+     * @return an unmodifiable collection of OFSwitchHandshakeHandlers
+     */
+    ImmutableList<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers();
+
+    /**
+     * Adds an OFSwitch driver
+     *  @param manufacturerDescriptionPrefix Register the given prefix
+     * with the driver.
+     * @param driver A IOFSwitchDriver instance to handle IOFSwitch instantiation
+     * for the given manufacturer description prefix
+     * @throws IllegalStateException If the the manufacturer description is
+     * already registered
+     * @throws NullPointerExeption if manufacturerDescriptionPrefix is null
+     * @throws NullPointerExeption if driver is null
+     */
+    void addOFSwitchDriver(String manufacturerDescriptionPrefix,
+                           IOFSwitchDriver driver);
+
+    /**
+     * Handles all changes to the switch status. Will alert listeners and manage
+     * the internal switch map appropriately.
+     * @param sw the switch that has changed
+     * @param oldStatus the switch's old status
+     * @param newStatus the switch's new status
+     */
+    void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus,
+            SwitchStatus newStatus);
+
+    /**
+     * Gets the number of connections required by the application
+     * @return the number of connections required by the applications
+     */
+    int getNumRequiredConnections();
+
+    /**
+     * Record a switch event in in-memory debug-event
+     * @param switchDpid
+     * @param reason Reason for this event
+     * @param flushNow see debug-event flushing in IDebugEventService
+     */
+    public void addSwitchEvent(DatapathId switchDpid, String reason, boolean flushNow);
+
+    /**
+     * Get the list of handshake plugins necessary for the switch handshake.
+     * @return the list of handshake plugins registered by applications.
+     */
+    List<IAppHandshakePluginFactory> getHandshakePlugins();
+
+    /**
+     * Get the switch manager's counters
+     * @return the switch manager's counters
+     */
+    SwitchManagerCounters getCounters();
+
+    /**
+     * Checks to see if the supplied category has been registered with the controller
+     * @param category the logical OF Message category to check or
+     * @return true if registered
+     */
+    boolean isCategoryRegistered(LogicalOFMessageCategory category);
+
+    void handshakeDisconnected(DatapathId dpid);
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchService.java b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchService.java
new file mode 100644
index 000000000..1896d2720
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/IOFSwitchService.java
@@ -0,0 +1,111 @@
+package net.floodlightcontroller.core.internal;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IOFSwitchListener;
+import net.floodlightcontroller.core.LogicalOFMessageCategory;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.core.rest.SwitchRepresentation;
+import org.projectfloodlight.openflow.types.DatapathId;
+
+public interface IOFSwitchService extends IFloodlightService {
+
+    /**
+     * Get's the switch map stored in the switch manager
+     * @return the map of switches known by the switch manager
+     */
+    Map<DatapathId, IOFSwitch> getAllSwitchMap();
+
+    /**
+     * If the switch with the given DPID is known to any controller in the
+     * cluster, this method returns the associated IOFSwitch instance. As such
+     * the returned switches not necessarily connected or in master role for
+     * the local controller.
+     *
+     * Multiple calls to this method with the same DPID may return different
+     * IOFSwitch references. A caller must not store or otherwise rely on
+     * IOFSwitch references to be constant over the lifecycle of a switch.
+     *
+     * @param dpid the dpid of the switch to query
+     * @return the IOFSwitch instance associated with the dpid, null if no
+     * switch with the dpid is known to the cluster
+     */
+    IOFSwitch getSwitch(DatapathId dpid);
+
+    /**
+     * If the switch with the given DPID is known to any controller in the
+     * cluster, this method returns the associated IOFSwitch instance. As such
+     * the returned switches not necessarily connected or in master role for
+     * the local controller.
+     *
+     * Multiple calls to this method with the same DPID may return different
+     * IOFSwitch references. A caller must not store or otherwise rely on
+     * IOFSwitch references to be constant over the lifecycle of a switch.
+     *
+     * @param dpid the dpid of the switch to query
+     * @return the IOFSwitch instance associated with the dpid, null if no
+     * switch with the dpid is known to the cluster OR if the switch status
+     * is not considered visible.
+     */
+    IOFSwitch getActiveSwitch(DatapathId dpid);
+
+    /**
+     * Add a switch listener
+     * @param listener The module that wants to listen for events
+     */
+    void addOFSwitchListener(IOFSwitchListener listener);
+
+    /**
+     * Remove a switch listener
+     * @param listener The The module that no longer wants to listen for events
+     */
+    void removeOFSwitchListener(IOFSwitchListener listener);
+
+    /**
+     * Registers a logical OFMessage category to be used by an application
+     * @param category the logical OFMessage category
+     */
+    void registerLogicalOFMessageCategory(LogicalOFMessageCategory category);
+
+    /**
+     * Registers an app handshake plugin to be used during switch handshaking.
+     * @param plugin the app handshake plugin to be used during switch handshaking.
+     */
+    void registerHandshakePlugin(IAppHandshakePluginFactory plugin);
+
+    /**
+     * Get the REST representations of the active switches.
+     * @return Representation wrappers of the active switches.
+     */
+    List<SwitchRepresentation> getSwitchRepresentations();
+
+    /**
+     * Get the REST representation of a switch.
+     * @param dpid the dpid of the desired switch representation.
+     * @return The switch representation.
+     */
+    SwitchRepresentation getSwitchRepresentation(DatapathId dpid);
+
+    /**
+     * Returns a snapshot of the set DPIDs for all known switches.
+     *
+     * The returned set is owned by the caller: the caller can modify it at
+     * will and changes to the known switches are not reflected in the returned
+     * set. The caller needs to call getAllSwitchDpids() if an updated
+     * version is needed.
+     *
+     * See {@link #getSwitch(long)} for what  "known" switch is.
+     * @return the set of DPIDs of all known switches
+     */
+    Set<DatapathId> getAllSwitchDpids();
+
+    /**
+     * Gets an immutable list of handshake handlers.
+     * @return an immutable list of handshake handlers.
+     */
+    List<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers();
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java
deleted file mode 100644
index 6251fd26d..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/ISwitchDriverRegistry.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package net.floodlightcontroller.core.internal;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.IOFSwitchDriver;
-
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
-
-/**
- * Maintain a registry for SwitchDrivers. Drivers can register with the
- * registry and a user can get IOFSwitch instances based on the switch's
- * OFDescriptionStatistics.
- *
- * A driver registers itself by specifying a <i>prefix string</i> of the
- * switch's <i>manufacturer</i> description. When a user request an
- * IOFSwitch instance the registry matches the manufacturer description
- * of the switch against the prefixes in the registry.
- *
- * See getOFSwitchInstance() for a description of the lookup contract
- *
- * @author gregor
- *
- */
-public interface ISwitchDriverRegistry {
-
-    /**
-     * Register an IOFSwitchDriver with the registry
-     *
-     * @param manufacturerDescriptionPrefix Register the given prefix
-     * with the driver.
-     * @param driver A IOFSwitchDriver instance to handle IOFSwitch instaniation
-     * for the given manufacturer description prefix
-     * @throws IllegalStateException If the the manufacturer description is
-     * already registered
-     * @throws NullPointerExeption if manufacturerDescriptionPrefix is null
-     * @throws NullPointerExeption if driver is null
-     */
-    void addSwitchDriver(String manufacturerDescriptionPrefix,
-                         IOFSwitchDriver driver);
-    /**
-     * Return an IOFSwitch instance according to the description stats.
-     *
-     * The driver with the <i>longest matching prefix</i> will be picked first.
-     * The description is then handed over to the choosen driver to return an
-     * IOFSwitch instance. If the driver does not return an IOFSwitch
-     * (returns null) the registry will continue to the next driver with
-     * a matching manufacturer description prefix. If no driver returns an
-     * IOFSwitch instance the registry returns a default OFSwitchImpl instance.
-     *
-     * The returned switch will have its description reply and
-     * switch properties set according to the DescriptionStats passed in
-     *
-     * @param description The OFDescriptionStatistics for which to return an
-     * IOFSwitch implementation
-     * @return A IOFSwitch implementation matching the description or an
-     * OFSwitchImpl if no driver returned a more concrete instance.
-     * @throws NullPointerException If the OFDescriptionStatistics or any
-     * of its members is null.
-     */
-    IOFSwitch getOFSwitchInstance(OFDescriptionStatistics description);
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/NaiiveSwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/NaiiveSwitchDriverRegistry.java
deleted file mode 100644
index 8109e3add..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/NaiiveSwitchDriverRegistry.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package net.floodlightcontroller.core.internal;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.IOFSwitchDriver;
-
-/**
- * This implementation of ISwitchDriverRegistry uses a naiive algorithm to
- * perform longest prefix matching on the manufacturere description prefixes
- *
- * We maintain a map that maps prefixes to the drivers as well as a sorted
- * set that contains the prefixes sorted by their length. We exploit the fact
- * that lexicographical order defines that shorter strings are always less
- * than longer strings with the same prefix). Thus we can use reverse order for
- * our purposes.
- * To perform a lookup we iterate through the sorted set until we find a prefix
- * that matches the manufacturer description. Since the set is sorted this
- * will be the longest matching prefix.
- *
- * @author gregor
- */
-class NaiiveSwitchDriverRegistry implements ISwitchDriverRegistry {
-    private final SortedSet<String> switchDescSorted;
-    private final Map<String,IOFSwitchDriver> switchBindingMap;
-
-    public NaiiveSwitchDriverRegistry() {
-        switchBindingMap = new HashMap<String, IOFSwitchDriver>();
-        switchDescSorted = new TreeSet<String>(Collections.reverseOrder());
-    }
-
-    @Override
-    public synchronized void addSwitchDriver(String manufacturerDescPrefix,
-                                             IOFSwitchDriver driver) {
-        if (manufacturerDescPrefix == null) {
-            throw new NullPointerException("manufacturerDescrptionPrefix" +
-                    " must not be null");
-        }
-        if (driver == null) {
-            throw new NullPointerException("driver must not be null");
-        }
-
-        IOFSwitchDriver existingDriver = switchBindingMap.get(manufacturerDescPrefix);
-        if (existingDriver != null ) {
-            throw new IllegalStateException("Failed to add OFSwitch driver for "
-                    + manufacturerDescPrefix + "already registered");
-        }
-        switchBindingMap.put(manufacturerDescPrefix, driver);
-        switchDescSorted.add(manufacturerDescPrefix);
-    }
-
-    @Override
-    // TODO: instead of synchronized we could actually use a r/w lock
-    // but it's probably not worth it.
-    public synchronized IOFSwitch
-            getOFSwitchInstance(OFDescriptionStatistics description) {
-        if (description == null)
-            throw new NullPointerException("description must not be null");
-        if (description.getHardwareDescription() == null) {
-            throw new NullPointerException(
-                    "hardware description must not be null");
-        }
-        if (description.getManufacturerDescription() == null) {
-            throw new NullPointerException(
-                    "manufacturer description must not be null");
-        }
-        if (description.getSerialNumber() == null) {
-            throw new NullPointerException(
-                    "serial number must not be null");
-        }
-        if (description.getDatapathDescription() == null) {
-            throw new NullPointerException(
-                    "datapath description must not be null");
-        }
-        if (description.getSoftwareDescription() == null) {
-            throw new NullPointerException(
-                    "software description must not be null");
-        }
-
-
-        // Find the appropriate driver
-        for (String descPrefix: switchDescSorted) {
-            if (description.getManufacturerDescription()
-                    .startsWith(descPrefix)) {
-                IOFSwitchDriver driver = switchBindingMap.get(descPrefix);
-                IOFSwitch sw = driver.getOFSwitchImpl(description);
-                if (sw != null) {
-                    sw.setSwitchProperties(description);
-                    return sw;
-                }
-            }
-        }
-        // no switch found
-        IOFSwitch sw = new OFSwitchImpl();
-        sw.setSwitchProperties(description);
-        return sw;
-    }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java b/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java
new file mode 100644
index 000000000..6f2fffed1
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/NaiveSwitchDriverRegistry.java
@@ -0,0 +1,102 @@
+package net.floodlightcontroller.core.internal;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.annotation.Nonnull;
+
+import net.floodlightcontroller.core.IOFConnectionBackend;
+import net.floodlightcontroller.core.IOFSwitchBackend;
+import net.floodlightcontroller.core.IOFSwitchDriver;
+import net.floodlightcontroller.core.OFSwitch;
+import net.floodlightcontroller.core.SwitchDescription;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * This implementation of ISwitchDriverRegistry uses a naive algorithm to
+ * perform longest prefix matching on the manufacturer description prefixes
+ *
+ * We maintain a map that maps prefixes to the drivers as well as a sorted
+ * set that contains the prefixes sorted by their length. We exploit the fact
+ * that lexicographical order defines that shorter strings are always less
+ * than longer strings with the same prefix). Thus we can use reverse order for
+ * our purposes.
+ * To perform a lookup we iterate through the sorted set until we find a prefix
+ * that matches the manufacturer description. Since the set is sorted this
+ * will be the longest matching prefix.
+ *
+ * @author gregor
+ */
+class NaiveSwitchDriverRegistry implements ISwitchDriverRegistry {
+
+    protected static final Logger log = LoggerFactory.getLogger(NaiveSwitchDriverRegistry.class);
+    private final SortedSet<String> switchDescSorted;
+    private final Map<String,IOFSwitchDriver> switchBindingMap;
+    private final IOFSwitchManager switchManager;
+
+    public NaiveSwitchDriverRegistry(@Nonnull IOFSwitchManager switchManager) {
+        Preconditions.checkNotNull(switchManager, "switchManager must not be null");
+        this.switchManager  = switchManager;
+        switchBindingMap = new HashMap<String, IOFSwitchDriver>();
+        switchDescSorted = new TreeSet<String>(Collections.reverseOrder());
+    }
+
+    @Override
+    public synchronized void addSwitchDriver(@Nonnull String manufacturerDescPrefix,
+                                             @Nonnull IOFSwitchDriver driver) {
+        Preconditions.checkNotNull(manufacturerDescPrefix, "manufactererDescProfix");
+        Preconditions.checkNotNull(driver, "driver");
+
+        IOFSwitchDriver existingDriver = switchBindingMap.get(manufacturerDescPrefix);
+        if (existingDriver != null ) {
+            throw new IllegalStateException("Failed to add OFSwitch driver for "
+                    + manufacturerDescPrefix + "already registered");
+        }
+        switchBindingMap.put(manufacturerDescPrefix, driver);
+        switchDescSorted.add(manufacturerDescPrefix);
+    }
+
+    @Override
+    // TODO: instead of synchronized we could actually use a r/w lock
+    // but it's probably not worth it.
+    public synchronized IOFSwitchBackend
+            getOFSwitchInstance(@Nonnull IOFConnectionBackend connection, @Nonnull SwitchDescription description,
+                    @Nonnull OFFactory factory, @Nonnull DatapathId id) {
+        Preconditions.checkNotNull(connection, "connection");
+        Preconditions.checkNotNull(description, "description");
+        Preconditions.checkNotNull(factory, "factory");
+        Preconditions.checkNotNull(id, "id");
+
+        Preconditions.checkNotNull(description.getHardwareDescription(), "hardware description");
+        Preconditions.checkNotNull(description.getManufacturerDescription(), "manufacturer description");
+        Preconditions.checkNotNull(description.getSerialNumber(), "serial number");
+        Preconditions.checkNotNull(description.getDatapathDescription(), "datapath description");
+        Preconditions.checkNotNull(description.getSoftwareDescription(), "software description");
+
+        // Find the appropriate driver
+        for (String descPrefix: switchDescSorted) {
+            if (description.getManufacturerDescription()
+                    .startsWith(descPrefix)) {
+                IOFSwitchDriver driver = switchBindingMap.get(descPrefix);
+                IOFSwitchBackend sw = driver.getOFSwitchImpl(description, factory);
+                if (sw != null) {
+                    sw.setSwitchProperties(description);
+                    return sw;
+                }
+            }
+        }
+        // no switch found
+        IOFSwitchBackend sw = new OFSwitch(connection, factory, switchManager, id);
+        sw.setSwitchProperties(description);
+        return sw;
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/NiciraRoleUtils.java b/src/main/java/net/floodlightcontroller/core/internal/NiciraRoleUtils.java
new file mode 100644
index 000000000..bf84d89a9
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/NiciraRoleUtils.java
@@ -0,0 +1,40 @@
+package net.floodlightcontroller.core.internal;
+
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply;
+
+/** static utilities to convert between Pre-OF1.2 "Nicira Style" roles and OF1.2+ OpenFlow
+ *  standard roles.
+ *  @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ */
+public class NiciraRoleUtils {
+    private NiciraRoleUtils() {}
+
+    public static OFControllerRole niciraToOFRole(OFNiciraControllerRoleReply roleReply) {
+        switch(roleReply.getRole()) {
+            case ROLE_MASTER:
+                return OFControllerRole.ROLE_MASTER;
+            case ROLE_OTHER:
+                return OFControllerRole.ROLE_EQUAL;
+            case ROLE_SLAVE:
+                return OFControllerRole.ROLE_SLAVE;
+            default:
+                throw new IllegalArgumentException("unknown Nicira role value: " + roleReply.getRole());
+        }
+    }
+
+    public static OFNiciraControllerRole ofRoleToNiciraRole(OFControllerRole role) {
+        switch(role) {
+            case ROLE_EQUAL:
+                return OFNiciraControllerRole.ROLE_OTHER;
+            case ROLE_MASTER:
+                return OFNiciraControllerRole.ROLE_MASTER;
+            case ROLE_SLAVE:
+                return OFNiciraControllerRole.ROLE_SLAVE;
+            default:
+                throw new IllegalArgumentException("Unknown role: " + role);
+        }
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutException.java b/src/main/java/net/floodlightcontroller/core/internal/OFAuxException.java
similarity index 51%
rename from src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutException.java
rename to src/main/java/net/floodlightcontroller/core/internal/OFAuxException.java
index 421ec1ac7..e2a6ccfdd 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/HandshakeTimeoutException.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFAuxException.java
@@ -1,7 +1,7 @@
 /**
-*    Copyright 2011, Big Switch Networks, Inc. 
+*    Copyright 2011, Big Switch Networks, Inc.
 *    Originally created by David Erickson, Stanford University
-* 
+*
 *    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
@@ -18,12 +18,25 @@
 package net.floodlightcontroller.core.internal;
 
 /**
- * Exception is thrown when the handshake fails to complete 
- * before a specified time
- * @author readams
+ * This exception indicates an error or unexpected message during
+ * OF Aux handshaking. E.g., if a switch reports that it cannot supply us
+ * with the number of OF Aux connections needed.
+ *  @author Jason Parraga <Jason.Parraga@bigswitch.com>
  */
-public class HandshakeTimeoutException extends Exception {
+public class OFAuxException extends SwitchStateException{
+
+        private static final long serialVersionUID = 8452081020837079086L;
+
+        public OFAuxException() {
+            super();
+        }
 
-    private static final long serialVersionUID = 6859880268940337312L;
+        public OFAuxException(String arg0) {
+            super(arg0);
+        }
 
-}
+        public OFAuxException(Throwable arg0) {
+            super(arg0);
+        }
+        
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
deleted file mode 100644
index 76f819ac9..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/OFChannelHandler.java
+++ /dev/null
@@ -1,1788 +0,0 @@
-package net.floodlightcontroller.core.internal;
-
-import java.io.IOException;
-import java.nio.channels.ClosedChannelException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.RejectedExecutionException;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.IFloodlightProviderService.Role;
-import net.floodlightcontroller.core.IOFSwitch.PortChangeEvent;
-import net.floodlightcontroller.core.annotations.LogMessageDoc;
-import net.floodlightcontroller.core.annotations.LogMessageDocs;
-import net.floodlightcontroller.core.internal.Controller.Counters;
-import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
-import net.floodlightcontroller.storage.IResultSet;
-import net.floodlightcontroller.storage.StorageException;
-import net.floodlightcontroller.util.LoadMonitor;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.ChannelStateEvent;
-import org.jboss.netty.channel.Channels;
-import org.jboss.netty.channel.ExceptionEvent;
-import org.jboss.netty.channel.MessageEvent;
-import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
-import org.jboss.netty.handler.timeout.IdleStateEvent;
-import org.jboss.netty.handler.timeout.ReadTimeoutException;
-import org.openflow.protocol.OFBarrierReply;
-import org.openflow.protocol.OFBarrierRequest;
-import org.openflow.protocol.OFEchoReply;
-import org.openflow.protocol.OFEchoRequest;
-import org.openflow.protocol.OFError;
-import org.openflow.protocol.OFFeaturesReply;
-import org.openflow.protocol.OFFlowRemoved;
-import org.openflow.protocol.OFGetConfigReply;
-import org.openflow.protocol.OFGetConfigRequest;
-import org.openflow.protocol.OFHello;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPortStatus;
-import org.openflow.protocol.OFQueueGetConfigReply;
-import org.openflow.protocol.OFSetConfig;
-import org.openflow.protocol.OFStatisticsReply;
-import org.openflow.protocol.OFStatisticsRequest;
-import org.openflow.protocol.OFSwitchConfig;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.OFVendor;
-import org.openflow.protocol.OFError.OFBadActionCode;
-import org.openflow.protocol.OFError.OFBadRequestCode;
-import org.openflow.protocol.OFError.OFErrorType;
-import org.openflow.protocol.OFError.OFFlowModFailedCode;
-import org.openflow.protocol.OFError.OFHelloFailedCode;
-import org.openflow.protocol.OFError.OFPortModFailedCode;
-import org.openflow.protocol.OFError.OFQueueOpFailedCode;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.factory.MessageParseException;
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
-import org.openflow.protocol.statistics.OFStatistics;
-import org.openflow.protocol.statistics.OFStatisticsType;
-import org.openflow.util.HexString;
-import org.openflow.vendor.nicira.OFNiciraVendorData;
-import org.openflow.vendor.nicira.OFRoleReplyVendorData;
-import org.openflow.vendor.nicira.OFRoleRequestVendorData;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.bigswitch.floodlight.vendor.OFBigSwitchVendorData;
-import com.bigswitch.floodlight.vendor.OFBsnL2TableSetVendorData;
-
-
-
-/**
- * Channel handler deals with the switch connection and dispatches
- * switch messages to the appropriate locations.
- * @author readams
- */
-class OFChannelHandler
-    extends IdleStateAwareChannelHandler {
-
-    private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
-
-    private static final long DEFAULT_ROLE_TIMEOUT_MS = 10*1000; // 10 sec
-
-    private final Controller controller;
-    private final Counters counters;
-    private IOFSwitch sw;
-    private Channel channel;
-    // State needs to be volatile because the HandshakeTimeoutHandler
-    // needs to check if the handshake is complete
-    private volatile ChannelState state;
-    private RoleChanger roleChanger;
-    private OFFeaturesReply featuresReply;
-
-    private final ArrayList<OFPortStatus> pendingPortStatusMsg;
-
-    /** transaction Ids to use during handshake. Since only one thread
-     * calls into the OFChannelHandler we don't need atomic.
-     * We will count down
-     */
-    private int handshakeTransactionIds = -1;
-
-
-
-    /**
-     * When we remove a pending role request and set the role on the switch
-     * we use this enum to indicate how we arrived at the decision.
-     * @author gregor
-     */
-    private enum RoleRecvStatus {
-        /** We receveived a role reply message from the switch */
-        RECEIVED_REPLY,
-        /** The switch returned an error indicated that roles are not
-         * supported*/
-        UNSUPPORTED,
-        /** The request timed out */
-        NO_REPLY;
-    }
-    /**
-     * A utility class to handle role requests and replies for this channel.
-     * After a role request is submitted the role changer keeps track of the
-     * pending request, collects the reply (if any) and times out the request
-     * if necessary.
-     *
-     * To simplify role handling we only keep track of the /last/ pending
-     * role reply send to the switch. If multiple requests are pending and
-     * we receive replies for earlier requests we ignore them. However, this
-     * way of handling pending requests implies that we could wait forever if
-     * a new request is submitted before the timeout triggers. If necessary
-     * we could work around that though.
-     * @author gregor
-     */
-    private class RoleChanger {
-        // indicates that a request is currently pending
-        // needs to be volatile to allow correct double-check idiom
-        private volatile boolean requestPending;
-        // the transactiong Id of the pending request
-        private int pendingXid;
-        // the role that's pending
-        private Role pendingRole;
-        // system time in MS when we send the request
-        private long roleSubmitTime;
-        // the timeout to use
-        private final long roleTimeoutMs;
-
-        public RoleChanger(long roleTimeoutMs) {
-            this.requestPending = false;
-            this.roleSubmitTime = 0;
-            this.pendingXid = -1;
-            this.pendingRole = null;
-            this.roleTimeoutMs = roleTimeoutMs;
-        }
-
-        /**
-         * Send NX role request message to the switch requesting the specified
-         * role.
-         *
-         * @param sw switch to send the role request message to
-         * @param role role to request
-         */
-        private int sendNxRoleRequest(Role role)
-                throws IOException {
-
-            int xid = sw.getNextTransactionId();
-            // Convert the role enum to the appropriate integer constant used
-            // in the NX role request message
-            int nxRole = role.toNxRole();
-
-            // Construct the role request message
-            OFVendor roleRequest = (OFVendor)BasicFactory.getInstance()
-                    .getMessage(OFType.VENDOR);
-            roleRequest.setXid(xid);
-            roleRequest.setVendor(OFNiciraVendorData.NX_VENDOR_ID);
-            OFRoleRequestVendorData roleRequestData = new OFRoleRequestVendorData();
-            roleRequestData.setRole(nxRole);
-            roleRequest.setVendorData(roleRequestData);
-            roleRequest.setLengthU(OFVendor.MINIMUM_LENGTH +
-                    roleRequestData.getLength());
-
-            // Send it to the switch
-            sw.write(Collections.<OFMessage>singletonList(roleRequest),
-                     new FloodlightContext());
-
-            return xid;
-        }
-
-        /**
-         * Send a role request for the given role only if no other role
-         * request is currently pending.
-         * @param role The role to send to the switch.
-         * @throws IOException
-         */
-        synchronized void sendRoleRequestIfNotPending(Role role)
-                throws IOException {
-            if (!requestPending)
-                sendRoleRequest(role);
-            else
-                counters.roleNotResentBecauseRolePending.updateCounterWithFlush();
-        }
-
-        /**
-         * Send a role request with the given role to the switch.
-         *
-         * Send a role request with the given role to the switch and update
-         * the pending request and timestamp.
-         *
-         * @param role
-         * @throws IOException
-         */
-        synchronized void sendRoleRequest(Role role) throws IOException {
-            /*
-             * There are three cases to consider for SUPPORTS_NX_ROLE:
-             *
-             * 1) unset. We have neither received a role reply from the
-             *    switch nor has a request timed out. Send a request.
-             * 2) TRUE: We've already send a request earlier and received
-             *    a reply. The switch supports role and we should send one.
-             * 3) FALSE: We have already send a role and received an error.
-             *    The switch does not support roles. Don't send a role request,
-             *    set the switch's role directly.
-             */
-            Boolean supportsNxRole = (Boolean)
-                    sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE);
-            if ((supportsNxRole != null) && !supportsNxRole) {
-                setSwitchRole(role, RoleRecvStatus.UNSUPPORTED);
-            } else {
-                pendingXid = sendNxRoleRequest(role);
-                pendingRole = role;
-                roleSubmitTime = System.currentTimeMillis();
-                requestPending = true;
-            }
-        }
-
-        /**
-         * Deliver a received role reply and set SWITCH_SUPPORTS_NX_ROLE.
-         *
-         * Check if a request is pending and if the received reply matches the
-         * the expected pending reply (we check both role and xid) we set
-         * the role for the switch/channel.
-         *
-         * If a request is pending but doesn't match the reply we ignore it.
-         *
-         * If no request is pending we disconnect.
-         *
-         * @param xid
-         * @param role
-         * @throws SwitchStateException if no request is pending
-         */
-        synchronized void deliverRoleReply(int xid, Role role) {
-            if (!requestPending) {
-                // Maybe don't disconnect if the role reply we received is
-                // for the same role we are already in.
-                String msg = String.format("Switch: [%s], State: [%s], "
-                                + "received unexpected RoleReply[%s]. "
-                                + "No roles are pending",
-                                OFChannelHandler.this.getSwitchInfoString(),
-                                OFChannelHandler.this.state.toString(),
-                                role);
-                throw new SwitchStateException(msg);
-            }
-
-            if (pendingXid == xid && pendingRole == role) {
-                log.debug("Received role reply message from {}, setting role to {}",
-                          getSwitchInfoString(), role);
-                counters.roleReplyReceived.updateCounterWithFlush();
-                setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY);
-            } else {
-                log.debug("Received stale or unexpected role reply from " +
-                          "switch {} ({}, xid={}). Ignoring. " +
-                          "Waiting for {}, xid={}",
-                          new Object[] { getSwitchInfoString(), role, xid,
-                                         pendingRole, pendingXid });
-            }
-        }
-
-        /**
-         * Called if we receive an  error message. If the xid matches the
-         * pending request we handle it otherwise we ignore it. We also
-         * set SWITCH_SUPPORTS_NX_ROLE to false.
-         *
-         * Note: since we only keep the last pending request we might get
-         * error messages for earlier role requests that we won't be able
-         * to handle
-         * @param xid
-         * @return true if the error was handled by us, false otherwise
-         * @throws SwitchStateException if the error was for the pending
-         * role request but was unexpected
-         */
-        synchronized boolean deliverError(OFError error) {
-            if (!requestPending)
-                return false;
-
-            if (pendingXid == error.getXid()) {
-                boolean isBadRequestError =
-                        (error.getErrorType() == OFError.OFErrorType.
-                        OFPET_BAD_REQUEST.getValue());
-                if (isBadRequestError) {
-                    counters.roleReplyErrorUnsupported.updateCounterWithFlush();
-                    setSwitchRole(pendingRole, RoleRecvStatus.UNSUPPORTED);
-                } else {
-                    // TODO: Is this the right thing to do if we receive
-                    // some other error besides a bad request error?
-                    // Presumably that means the switch did actually
-                    // understand the role request message, but there
-                    // was some other error from processing the message.
-                    // OF 1.2 specifies a OFPET_ROLE_REQUEST_FAILED
-                    // error code, but it doesn't look like the Nicira
-                    // role request has that. Should check OVS source
-                    // code to see if it's possible for any other errors
-                    // to be returned.
-                    // If we received an error the switch is not
-                    // in the correct role, so we need to disconnect it.
-                    // We could also resend the request but then we need to
-                    // check if there are other pending request in which
-                    // case we shouldn't resend. If we do resend we need
-                    // to make sure that the switch eventually accepts one
-                    // of our requests or disconnect the switch. This feels
-                    // cumbersome.
-                    String msg = String.format("Switch: [%s], State: [%s], "
-                                    + "Unexpected error %s in respone to our "
-                                    + "role request for %s.",
-                                    OFChannelHandler.this.getSwitchInfoString(),
-                                    OFChannelHandler.this.state.toString(),
-                                    getErrorString(error),
-                                    pendingRole);
-                    throw new SwitchStateException(msg);
-                }
-                return true;
-            }
-            return false;
-        }
-
-        /**
-         * Check if a pending role request has timed out.
-         */
-        void checkTimeout() {
-            if (!requestPending)
-                return;
-            synchronized(this) {
-                if (!requestPending)
-                    return;
-                long now = System.currentTimeMillis();
-                if (now - roleSubmitTime > roleTimeoutMs) {
-                    // timeout triggered.
-                    counters.roleReplyTimeout.updateCounterWithFlush();
-                    setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY);
-                }
-            }
-        }
-
-        /**
-         * Set the role for this switch / channel.
-         *
-         * If the status indicates that we received a reply we set the role.
-         * If the status indicates otherwise we disconnect the switch if
-         * the role is SLAVE.
-         *
-         * "Setting a role" means setting the appropriate ChannelState,
-         * setting the flags on the switch and
-         * notifying Controller.java about new role of the switch
-         *
-         * @param role The role to set.
-         * @param status How we derived at the decision to set this status.
-         */
-        synchronized private void setSwitchRole(Role role, RoleRecvStatus status) {
-            requestPending = false;
-            if (status == RoleRecvStatus.RECEIVED_REPLY)
-                sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
-            else
-                sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
-            sw.setHARole(role);
-
-            if (role != Role.SLAVE) {
-                OFChannelHandler.this.setState(ChannelState.MASTER);
-                // TODO: should we really activate the switch again if it's
-                // already master??
-                if (log.isDebugEnabled()) {
-                    log.debug("Switch {} activated. Role is now MASTER",
-                              getSwitchInfoString());
-                }
-                controller.switchActivated(OFChannelHandler.this.sw);
-            } else {
-                OFChannelHandler.this.setState(ChannelState.SLAVE);
-                if (status != RoleRecvStatus.RECEIVED_REPLY) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Disconnecting switch {}. Doesn't support role"
-                              + "({}) request and controller is now SLAVE",
-                              getSwitchInfoString(), status);
-                    }
-                    // the disconnect will trigger a switch removed to
-                    // controller so no need to signal anything else
-                    sw.disconnectOutputStream();
-                } else {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Switch {} is now SLAVE",
-                                  getSwitchInfoString());
-                    }
-                    controller.switchDeactivated(OFChannelHandler.this.sw);
-                }
-            }
-        }
-    }
-
-
-    /**
-     * The state machine for handling the switch/channel state.
-     * @author gregor
-     */
-    enum ChannelState {
-        /**
-         * Initial state before channel is connected.
-         */
-        INIT(false) {
-            @Override
-            void
-            processOFMessage(OFChannelHandler h, OFMessage m)
-                    throws IOException {
-                illegalMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFError(OFChannelHandler h, OFError m)
-                    throws IOException {
-                // need to implement since its abstract but it will never
-                // be called
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                unhandledMessageReceived(h, m);
-            }
-        },
-
-        /**
-         * We send a HELLO to the switch and wait for a reply.
-         * Once we receive the reply we send an OFFeaturesRequest and
-         * a request to clear all FlowMods.
-         * Next state is WAIT_FEATURES_REPLY
-         */
-        WAIT_HELLO(false) {
-            @Override
-            void processOFHello(OFChannelHandler h, OFHello m)
-                    throws IOException {
-                h.sendHandShakeMessage(OFType.FEATURES_REQUEST);
-                h.setState(WAIT_FEATURES_REPLY);
-            }
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException {
-                illegalMessageReceived(h, m);
-            }
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                                          OFStatisticsReply  m)
-                    throws IOException {
-                illegalMessageReceived(h, m);
-            }
-            @Override
-            void processOFError(OFChannelHandler h, OFError m) {
-                logErrorDisconnect(h, m);
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                unhandledMessageReceived(h, m);
-            }
-        },
-
-        /**
-         * We are waiting for a features reply message. Once we receive it
-         * we send a SetConfig request, barrier, and GetConfig request.
-         * Next stats is WAIT_CONFIG_REPLY or WAIT_SET_L2_TABLE_REPLY
-         */
-        WAIT_FEATURES_REPLY(false) {
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException {
-                h.featuresReply = m;
-                if (m.getTables() > 1) {
-                    log.debug("Have {} table for switch {}", m.getTables(),
-                              h.getSwitchInfoString());
-                    // likely supports L2 table extensions. Send set
-                    h.sendHandshakeL2TableSet();
-                    // TODO: no L2 SET reply yet, so fire and forget the set
-                    // table message and move directly to sendHandshakeConfig
-                    h.sendHandshakeSetConfig();
-                    h.setState(WAIT_CONFIG_REPLY);
-                    //h.setState(WAIT_SET_L2_TABLE_REPLY);
-                } else {
-                    h.sendHandshakeSetConfig();
-                    h.setState(WAIT_CONFIG_REPLY);
-                }
-            }
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                                          OFStatisticsReply  m)
-                    throws IOException {
-                illegalMessageReceived(h, m);
-            }
-            @Override
-            void processOFError(OFChannelHandler h, OFError m) {
-                logErrorDisconnect(h, m);
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                unhandledMessageReceived(h, m);
-            }
-        },
-
-        WAIT_SET_L2_TABLE_REPLY(false) {
-            @Override void processOFVendor(OFChannelHandler h, OFVendor m)
-                    throws IOException {
-                // TODO: actually parse the response
-                h.sendHandshakeSetConfig();
-                h.setState(WAIT_CONFIG_REPLY);
-            };
-
-            @Override
-            void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) {
-                // do nothing;
-            }
-
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException {
-                // TODO: we could re-set the features reply
-                illegalMessageReceived(h, m);
-            }
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                                          OFStatisticsReply  m)
-                    throws IOException {
-                illegalMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFError(OFChannelHandler h, OFError m) {
-                logErrorDisconnect(h, m);
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                h.pendingPortStatusMsg.add(m);
-            }
-        },
-
-        /**
-         * We are waiting for a config reply message. Once we receive it
-         * we send a DescriptionStatsRequest to the switch.
-         * Next state: WAIT_DESCRIPTION_STAT_REPLY
-         */
-        WAIT_CONFIG_REPLY(false) {
-            @Override
-            @LogMessageDocs({
-                @LogMessageDoc(level="WARN",
-                        message="Config Reply from {switch} has " +
-                                "miss length set to {length}",
-                        explanation="The controller requires that the switch " +
-                                "use a miss length of 0xffff for correct " +
-                                "function",
-                        recommendation="Use a different switch to ensure " +
-                                "correct function")
-            })
-            void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m)
-                    throws IOException {
-                if (m.getMissSendLength() == (short)0xffff) {
-                    log.trace("Config Reply from switch {} confirms "
-                            + "miss length set to 0xffff",
-                            h.getSwitchInfoString());
-                } else {
-                    // FIXME: we can't really deal with switches that don't send
-                    // full packets. Shouldn't we drop the connection here?
-                    // FIXME: count??
-                    log.warn("Config Reply from switch {} has"
-                            + "miss length set to {}",
-                            h.getSwitchInfoString(),
-                            m.getMissSendLength());
-                }
-                h.sendHandshakeDescriptionStatsRequest();
-                h.setState(WAIT_DESCRIPTION_STAT_REPLY);
-            }
-
-            @Override
-            void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) {
-                // do nothing;
-            }
-
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException {
-                // TODO: we could re-set the features reply
-                illegalMessageReceived(h, m);
-            }
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                                          OFStatisticsReply  m)
-                    throws IOException {
-                illegalMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFError(OFChannelHandler h, OFError m) {
-                if (m.getErrorType() == OFErrorType.OFPET_BAD_REQUEST.getValue()
-                        && m.getErrorCode() ==
-                            OFBadRequestCode.OFPBRC_BAD_VENDOR.ordinal()) {
-                    log.debug("Switch {} has multiple tables but does not " +
-                            "support L2 table extension",
-                            h.getSwitchInfoString());
-                    return;
-                }
-                logErrorDisconnect(h, m);
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                h.pendingPortStatusMsg.add(m);
-            }
-        },
-
-        /**
-         * We are waiting for a OFDescriptionStat message from teh switch.
-         * Once we receive any stat message we try to parse it. If it's not
-         * a description stats message we disconnect. If its the expected
-         * description stats message, we:
-         *    - use the switch driver to bind the switch and get an IOFSwitch
-         *      instance, setup the switch instance
-         *    - setup the IOFSwitch instance
-         *    - add switch to FloodlightProvider and send the intial role
-         *      request to the switch.
-         * Next state: WAIT_INITIAL_ROLE
-         * All following states will have a h.sw instance!
-         */
-        WAIT_DESCRIPTION_STAT_REPLY(false) {
-            @LogMessageDoc(message="Switch {switch info} bound to class " +
-                "{switch driver}, description {switch description}",
-                    explanation="The specified switch has been bound to " +
-                            "a switch driver based on the switch description" +
-                            "received from the switch")
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                                          OFStatisticsReply m) {
-                // Read description, if it has been updated
-                OFDescriptionStatistics description =
-                        new OFDescriptionStatistics();
-                ChannelBuffer data =
-                        ChannelBuffers.buffer(description.getLength());
-                OFStatistics f = m.getFirstStatistics();
-                f.writeTo(data);
-                description.readFrom(data);
-                h.sw = h.controller.getOFSwitchInstance(description);
-                // set switch information
-                // set features reply and channel first so we a DPID and
-                // channel info.
-                h.sw.setFeaturesReply(h.featuresReply);
-                h.sw.setConnected(true);
-                h.sw.setChannel(h.channel);
-                h.sw.setFloodlightProvider(h.controller);
-                h.sw.setThreadPoolService(h.controller.getThreadPoolService());
-                try {
-                    h.sw.setDebugCounterService(h.controller.getDebugCounter());
-                } catch (CounterException e) {
-                    h.counters.switchCounterRegistrationFailed
-                            .updateCounterNoFlush();
-                    log.warn("Could not register counters for switch {} ",
-                              h.getSwitchInfoString(), e);
-                }
-                h.sw.setAccessFlowPriority(h.controller.getAccessFlowPriority());
-                h.sw.setCoreFlowPriority(h.controller.getCoreFlowPriority());
-                for (OFPortStatus ps: h.pendingPortStatusMsg)
-                    handlePortStatusMessage(h, ps, false);
-                h.pendingPortStatusMsg.clear();
-                h.readPropertyFromStorage();
-                log.info("Switch {} bound to class {}, writeThrottle={}," +
-                        " description {}",
-                         new Object[] { h.sw, h.sw.getClass(),
-                                        h.sw.isWriteThrottleEnabled(),
-                                    description });
-                h.sw.startDriverHandshake();
-                if (h.sw.isDriverHandshakeComplete())
-                    h.gotoWaitInitialRoleState();
-                else
-                    h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
-            }
-
-            @Override
-            void processOFError(OFChannelHandler h, OFError m) {
-                logErrorDisconnect(h, m);
-            }
-
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException {
-                // TODO: we could re-set the features reply
-                illegalMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                h.pendingPortStatusMsg.add(m);
-            }
-        },
-
-        WAIT_SWITCH_DRIVER_SUB_HANDSHAKE(false) {
-            @Override
-            void processOFError(OFChannelHandler h, OFError m)
-                    throws IOException {
-                // will never be called. We override processOFMessage
-            }
-
-            @Override
-            void processOFMessage(OFChannelHandler h, OFMessage m)
-                    throws IOException {
-                if (m.getType() == OFType.ECHO_REQUEST)
-                    processOFEchoRequest(h, (OFEchoRequest)m);
-                else {
-                    // FIXME: other message to handle here?
-                    h.sw.processDriverHandshakeMessage(m);
-                    if (h.sw.isDriverHandshakeComplete()) {
-                        h.gotoWaitInitialRoleState();
-                    }
-                }
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                handlePortStatusMessage(h, m, false);
-            }
-        },
-
-        /**
-         * We are waiting for the intial role reply message (or error
-         * indication) from the switch.
-         * Next State: MASTER or SLAVE
-         */
-        WAIT_INITIAL_ROLE(false) {
-            @Override
-            void processOFError(OFChannelHandler h, OFError m) {
-                // role changer will ignore the error if it isn't for it
-                boolean didHandle = h.roleChanger.deliverError(m);
-                if (!didHandle) {
-                    logError(h, m);
-                }
-            }
-
-            @Override
-            void processOFVendor(OFChannelHandler h, OFVendor m)
-                    throws IOException {
-                Role role = extractNiciraRoleReply(h, m);
-                // If role == null it measn the message wasn't really a
-                // Nicira role reply. We ignore this case.
-                if (role != null)
-                    h.roleChanger.deliverRoleReply(m.getXid(), role);
-                else
-                    unhandledMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException {
-                // TODO: we could re-set the features reply
-                illegalMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                                          OFStatisticsReply m) {
-                illegalMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                handlePortStatusMessage(h, m, false);
-
-            }
-        },
-
-        /**
-         * The switch is in MASTER role. We enter this state after a role
-         * reply from the switch is received (or the controller is MASTER
-         * and the switch doesn't support roles). The handshake is complete at
-         * this point. We only leave this state if the switch disconnects or
-         * if we send a role request for SLAVE /and/ receive the role reply for
-         * SLAVE.
-         */
-        MASTER(true) {
-            @LogMessageDoc(level="WARN",
-                message="Received permission error from switch {} while" +
-                         "being master. Reasserting master role.",
-                explanation="The switch has denied an operation likely " +
-                         "indicating inconsistent controller roles",
-                recommendation="This situation can occurs transiently during role" +
-                 " changes. If, however, the condition persists or happens" +
-                 " frequently this indicates a role inconsistency. " +
-                 LogMessageDoc.CHECK_CONTROLLER )
-            @Override
-            void processOFError(OFChannelHandler h, OFError m)
-                    throws IOException {
-                // role changer will ignore the error if it isn't for it
-                boolean didHandle = h.roleChanger.deliverError(m);
-                if (didHandle)
-                    return;
-                if (m.getErrorType() ==
-                        OFErrorType.OFPET_BAD_REQUEST.getValue() &&
-                   m.getErrorCode() ==
-                        OFBadRequestCode.OFPBRC_EPERM.ordinal()) {
-                    // We are the master controller and the switch returned
-                    // a permission error. This is a likely indicator that
-                    // the switch thinks we are slave. Reassert our
-                    // role
-                    // FIXME: this could be really bad during role transitions
-                    // if two controllers are master (even if its only for
-                    // a brief period). We might need to see if these errors
-                    // persist before we reassert
-                    h.counters.epermErrorWhileSwitchIsMaster.updateCounterWithFlush();
-                    log.warn("Received permission error from switch {} while" +
-                             "being master. Reasserting master role.",
-                             h.getSwitchInfoString());
-                    h.controller.reassertRole(h, Role.MASTER);
-                }
-                else if (m.getErrorType() ==
-                        OFErrorType.OFPET_PORT_MOD_FAILED.getValue() &&
-                    m.getErrorCode() ==
-                        OFFlowModFailedCode.OFPFMFC_ALL_TABLES_FULL.ordinal()) {
-                    h.sw.setTableFull(true);
-                }
-                else {
-                    logError(h, m);
-                }
-                h.dispatchMessage(m);
-            }
-
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                                          OFStatisticsReply m) {
-                h.sw.deliverStatisticsReply(m);
-            }
-
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException {
-                h.sw.setFeaturesReply(m);
-                h.sw.deliverOFFeaturesReply(m);
-            }
-
-            @Override
-            void processOFVendor(OFChannelHandler h, OFVendor m)
-                    throws IOException {
-                Role role = extractNiciraRoleReply(h, m);
-                // If role == null it means the message wasn't really a
-                // Nicira role reply. We ignore just dispatch it to the
-                // OFMessage listenersa in this case.
-                if (role != null)
-                    h.roleChanger.deliverRoleReply(m.getXid(), role);
-                else
-                    h.dispatchMessage(m);
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                handlePortStatusMessage(h, m, true);
-            }
-
-            @Override
-            void processOFPacketIn(OFChannelHandler h, OFPacketIn m) throws IOException {
-                h.dispatchMessage(m);
-            }
-
-            @Override
-            void processOFFlowRemoved(OFChannelHandler h,
-                                      OFFlowRemoved m) throws IOException {
-                h.dispatchMessage(m);
-            }
-            @Override
-            void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) throws IOException{
-                h.dispatchMessage(m);
-            }
-        },
-
-        /**
-         * The switch is in SLAVE role. We enter this state after a role
-         * reply from the switch is received. The handshake is complete at
-         * this point. We only leave this state if the switch disconnects or
-         * if we send a role request for MASTER /and/ receive the role reply for
-         * MASTER.
-         * TODO: CURRENTLY, WE DO NOT DISPATCH ANY MESSAGE IN SLAVE.
-         */
-        SLAVE(true) {
-            @Override
-            void processOFError(OFChannelHandler h, OFError m)
-                    throws IOException {
-                // role changer will ignore the error if it isn't for it
-                boolean didHandle = h.roleChanger.deliverError(m);
-                if (!didHandle) {
-                    logError(h, m);
-                }
-            }
-
-
-
-            @Override
-            void processOFStatisticsReply(OFChannelHandler h,
-                                          OFStatisticsReply m) {
-                // FIXME.
-                h.sw.deliverStatisticsReply(m);
-            }
-
-            @Override
-            void processOFVendor(OFChannelHandler h, OFVendor m)
-                    throws IOException {
-                Role role = extractNiciraRoleReply(h, m);
-                // If role == null it means the message wasn't really a
-                // Nicira role reply. We ignore it.
-                if (role != null)
-                    h.roleChanger.deliverRoleReply(m.getXid(), role);
-                else
-                    unhandledMessageReceived(h, m);
-            }
-
-            @Override
-            void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                    throws IOException {
-                // do nothing
-            }
-
-            @Override
-            void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                    throws IOException {
-                // do nothing
-            }
-
-            @Override
-            @LogMessageDoc(level="WARN",
-                message="Received PacketIn from switch {} while" +
-                         "being slave. Reasserting slave role.",
-                explanation="The switch has receive a PacketIn despite being " +
-                         "in slave role indicating inconsistent controller roles",
-                recommendation="This situation can occurs transiently during role" +
-                         " changes. If, however, the condition persists or happens" +
-                         " frequently this indicates a role inconsistency. " +
-                         LogMessageDoc.CHECK_CONTROLLER )
-            void processOFPacketIn(OFChannelHandler h, OFPacketIn m) throws IOException {
-                // we don't expect packetIn while slave, reassert we are slave
-                h.counters.packetInWhileSwitchIsSlave.updateCounterNoFlush();
-                log.warn("Received PacketIn from switch {} while" +
-                         "being slave. Reasserting slave role.", h.sw);
-                h.controller.reassertRole(h, Role.SLAVE);
-            }
-        };
-
-        private final boolean handshakeComplete;
-        ChannelState(boolean handshakeComplete) {
-            this.handshakeComplete = handshakeComplete;
-        }
-
-        /**
-         * Is this a state in which the handshake has completed?
-         * @return true if the handshake is complete
-         */
-        public boolean isHandshakeComplete() {
-            return handshakeComplete;
-        }
-
-        /**
-         * Get a string specifying the switch connection, state, and
-         * message received. To be used as message for SwitchStateException
-         * or log messages
-         * @param h The channel handler (to get switch information_
-         * @param m The OFMessage that has just been received
-         * @param details A string giving more details about the exact nature
-         * of the problem.
-         * @return
-         */
-        // needs to be protected because enum members are acutally subclasses
-        protected String getSwitchStateMessage(OFChannelHandler h,
-                                                      OFMessage m,
-                                                      String details) {
-            return String.format("Switch: [%s], State: [%s], received: [%s]"
-                                 + ", details: %s",
-                                 h.getSwitchInfoString(),
-                                 this.toString(),
-                                 m.getType().toString(),
-                                 details);
-        }
-
-        /**
-         * We have an OFMessage we didn't expect given the current state and
-         * we want to treat this as an error.
-         * We currently throw an exception that will terminate the connection
-         * However, we could be more forgiving
-         * @param h the channel handler that received the message
-         * @param m the message
-         * @throws SwitchStateExeption we always through the execption
-         */
-        // needs to be protected because enum members are acutally subclasses
-        protected void illegalMessageReceived(OFChannelHandler h, OFMessage m) {
-            String msg = getSwitchStateMessage(h, m,
-                    "Switch should never send this message in the current state");
-            throw new SwitchStateException(msg);
-
-        }
-
-        /**
-         * We have an OFMessage we didn't expect given the current state and
-         * we want to ignore the message
-         * @param h the channel handler the received the message
-         * @param m the message
-         */
-        protected void unhandledMessageReceived(OFChannelHandler h,
-                                                OFMessage m) {
-            h.counters.unhandledMessage.updateCounterNoFlush();
-            if (log.isDebugEnabled()) {
-                String msg = getSwitchStateMessage(h, m,
-                        "Ignoring unexpected message");
-                log.debug(msg);
-            }
-        }
-
-        /**
-         * Log an OpenFlow error message from a switch
-         * @param sw The switch that sent the error
-         * @param error The error message
-         */
-        @LogMessageDoc(level="ERROR",
-                message="Error {error type} {error code} from {switch} " +
-                        "in state {state}",
-                explanation="The switch responded with an unexpected error" +
-                        "to an OpenFlow message from the controller",
-                recommendation="This could indicate improper network operation. " +
-                        "If the problem persists restarting the switch and " +
-                        "controller may help."
-                )
-        protected void logError(OFChannelHandler h, OFError error) {
-            log.error("{} from switch {} in state {}",
-                      new Object[] {
-                          getErrorString(error),
-                          h.getSwitchInfoString(),
-                          this.toString()});
-        }
-
-        /**
-         * Log an OpenFlow error message from a switch and disconnect the
-         * channel
-         * @param sw The switch that sent the error
-         * @param error The error message
-         */
-        protected void logErrorDisconnect(OFChannelHandler h, OFError error) {
-            logError(h, error);
-            h.channel.disconnect();
-        }
-
-
-        /**
-         * Extract the role from an OFVendor message.
-         *
-         * Extract the role from an OFVendor message if the message is a
-         * Nicira role reply. Otherwise return null.
-         *
-         * @param h The channel handler receiving the message
-         * @param vendorMessage The vendor message to parse.
-         * @return The role in the message if the message is a Nicira role
-         * reply, null otherwise.
-         * @throws SwitchStateException If the message is a Nicira role reply
-         * but the numeric role value is unknown.
-         * FIXME: The message parser should make sure that the Nicira role is
-         * actually valid. Why do we need to take care of it ?!?
-         */
-        protected Role extractNiciraRoleReply(OFChannelHandler h,
-                                              OFVendor vendorMessage) {
-            int vendor = vendorMessage.getVendor();
-            if (vendor != OFNiciraVendorData.NX_VENDOR_ID)
-                return null;
-            if (! (vendorMessage.getVendorData() instanceof OFRoleReplyVendorData))
-                return null;
-            OFRoleReplyVendorData roleReplyVendorData =
-                    (OFRoleReplyVendorData) vendorMessage.getVendorData();
-            Role role = Role.fromNxRole(roleReplyVendorData.getRole());
-            if (role == null) {
-                String msg = String.format("Switch: [%s], State: [%s], "
-                        + "received NX_ROLE_REPLY with invalid role "
-                        + "value %d",
-                        h.getSwitchInfoString(),
-                        this.toString(),
-                        roleReplyVendorData.getRole());
-                throw new SwitchStateException(msg);
-            }
-            return role;
-        }
-
-        /**
-         * Handle a port status message.
-         *
-         * Handle a port status message by updating the port maps in the
-         * IOFSwitch instance and notifying Controller about the change so
-         * it can dispatch a switch update.
-         *
-         * @param h The OFChannelHhandler that received the message
-         * @param m The PortStatus message we received
-         * @param doNotify if true switch port changed events will be
-         * dispatched
-         */
-        protected void handlePortStatusMessage(OFChannelHandler h,
-                                               OFPortStatus m,
-                                               boolean doNotify) {
-            if (h.sw == null) {
-                String msg = getSwitchStateMessage(h, m,
-                        "State machine error: switch is null. Should never " +
-                        "happen");
-                throw new SwitchStateException(msg);
-            }
-            Collection<PortChangeEvent> changes = h.sw.processOFPortStatus(m);
-            if (doNotify) {
-                for (PortChangeEvent ev: changes)
-                    h.controller.notifyPortChanged(h.sw, ev.port, ev.type);
-            }
-        }
-
-        /**
-         * Process an OF message received on the channel and
-         * update state accordingly.
-         *
-         * The main "event" of the state machine. Process the received message,
-         * send follow up message if required and update state if required.
-         *
-         * Switches on the message type and calls more specific event handlers
-         * for each individual OF message type. If we receive a message that
-         * is supposed to be sent from a controller to a switch we throw
-         * a SwitchStateExeption.
-         *
-         * The more specific handlers can also throw SwitchStateExceptions
-         *
-         * @param h The OFChannelHandler that received the message
-         * @param m The message we received.
-         * @throws SwitchStateException
-         * @throws IOException
-         */
-        void processOFMessage(OFChannelHandler h, OFMessage m) throws IOException {
-            h.roleChanger.checkTimeout();
-            switch(m.getType()) {
-                case HELLO:
-                    processOFHello(h, (OFHello)m);
-                    break;
-                case BARRIER_REPLY:
-                    processOFBarrierReply(h, (OFBarrierReply)m);
-                    break;
-                case ECHO_REPLY:
-                    processOFEchoReply(h, (OFEchoReply)m);
-                    break;
-                case ECHO_REQUEST:
-                    processOFEchoRequest(h, (OFEchoRequest)m);
-                    break;
-                case ERROR:
-                    processOFError(h, (OFError)m);
-                    break;
-                case FEATURES_REPLY:
-                    processOFFeaturesReply(h, (OFFeaturesReply)m);
-                    break;
-                case FLOW_REMOVED:
-                    processOFFlowRemoved(h, (OFFlowRemoved)m);
-                    break;
-                case GET_CONFIG_REPLY:
-                    processOFGetConfigReply(h, (OFGetConfigReply)m);
-                    break;
-                case PACKET_IN:
-                    processOFPacketIn(h, (OFPacketIn)m);
-                    break;
-                case PORT_STATUS:
-                    processOFPortStatus(h, (OFPortStatus)m);
-                    break;
-                case QUEUE_GET_CONFIG_REPLY:
-                    processOFQueueGetConfigReply(h, (OFQueueGetConfigReply)m);
-                    break;
-                case STATS_REPLY:
-                    processOFStatisticsReply(h, (OFStatisticsReply)m);
-                    break;
-                case VENDOR:
-                    processOFVendor(h, (OFVendor)m);
-                    break;
-                // The following messages are sent to switches. The controller
-                // should never receive them
-                case SET_CONFIG:
-                case GET_CONFIG_REQUEST:
-                case PACKET_OUT:
-                case PORT_MOD:
-                case QUEUE_GET_CONFIG_REQUEST:
-                case BARRIER_REQUEST:
-                case STATS_REQUEST:
-                case FEATURES_REQUEST:
-                case FLOW_MOD:
-                    illegalMessageReceived(h, m);
-                    break;
-            }
-        }
-
-        /*-----------------------------------------------------------------
-         * Default implementation for message handlers in any state.
-         *
-         * Individual states must override these if they want a behavior
-         * that differs from the default.
-         *
-         * In general, these handlers simply ignore the message and do
-         * nothing.
-         *
-         * There are some exceptions though, since some messages really
-         * are handled the same way in every state (e.g., ECHO_REQUST) or
-         * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY
-         -----------------------------------------------------------------*/
-
-        void processOFHello(OFChannelHandler h, OFHello m) throws IOException {
-            // we only expect hello in the WAIT_HELLO state
-            illegalMessageReceived(h, m);
-        }
-
-        void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m)
-                throws IOException {
-            // Silently ignore.
-        }
-
-        void processOFEchoRequest(OFChannelHandler h, OFEchoRequest m)
-            throws IOException {
-            OFEchoReply reply = (OFEchoReply)
-                    BasicFactory.getInstance().getMessage(OFType.ECHO_REPLY);
-            reply.setXid(m.getXid());
-            reply.setPayload(m.getPayload());
-            reply.setLengthU(m.getLengthU());
-            h.channel.write(Collections.singletonList(reply));
-        }
-
-        void processOFEchoReply(OFChannelHandler h, OFEchoReply m)
-            throws IOException {
-            // Do nothing with EchoReplies !!
-        }
-
-        // no default implementation for OFError
-        // every state must override it
-        abstract void processOFError(OFChannelHandler h, OFError m)
-                throws IOException;
-
-
-        void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply  m)
-                throws IOException {
-            unhandledMessageReceived(h, m);
-        }
-
-        void processOFFlowRemoved(OFChannelHandler h, OFFlowRemoved m)
-            throws IOException {
-            unhandledMessageReceived(h, m);
-        }
-
-        void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m)
-                throws IOException {
-            // we only expect config replies in the WAIT_CONFIG_REPLY state
-            // TODO: might use two different strategies depending on whether
-            // we got a miss length of 64k or not.
-            illegalMessageReceived(h, m);
-        }
-
-        void processOFPacketIn(OFChannelHandler h, OFPacketIn m)
-                throws IOException {
-            unhandledMessageReceived(h, m);
-        }
-
-        // bi default implementation. Every state needs to handle it.
-        abstract void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
-                throws IOException;
-
-        void processOFQueueGetConfigReply(OFChannelHandler h,
-                                          OFQueueGetConfigReply m)
-                throws IOException {
-            unhandledMessageReceived(h, m);
-        }
-
-        void processOFStatisticsReply(OFChannelHandler h, OFStatisticsReply m)
-                throws IOException {
-            unhandledMessageReceived(h, m);
-        }
-
-        void processOFVendor(OFChannelHandler h, OFVendor m)
-                throws IOException {
-            // TODO: it might make sense to parse the vendor message here
-            // into the known vendor messages we support and then call more
-            // spefic event handlers
-            unhandledMessageReceived(h, m);
-        }
-    }
-
-
-    /**
-     * Create a new unconnecte OFChannelHandler.
-     * @param controller
-     */
-    OFChannelHandler(Controller controller) {
-        this.controller = controller;
-        this.counters = controller.getCounters();
-        this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_MS);
-        this.state = ChannelState.INIT;
-        this.pendingPortStatusMsg = new ArrayList<OFPortStatus>();
-    }
-
-    /**
-     * Is this a state in which the handshake has completed?
-     * @return true if the handshake is complete
-     */
-    boolean isHandshakeComplete() {
-        return this.state.isHandshakeComplete();
-    }
-
-    /**
-     * Forwards to RoleChanger. See there.
-     * @param role
-     */
-    void sendRoleRequestIfNotPending(Role role) {
-        try {
-            roleChanger.sendRoleRequestIfNotPending(role);
-        } catch (IOException e) {
-             log.error("Disconnecting switch {} due to IO Error: {}",
-                              getSwitchInfoString(), e.getMessage());
-             channel.close();
-        }
-    }
-
-    /**
-     * Forwards to RoleChanger. See there.
-     * @param role
-     */
-    void sendRoleRequest(Role role) {
-        try {
-            roleChanger.sendRoleRequest(role);
-        } catch (IOException e) {
-             log.error("Disconnecting switch {} due to IO Error: {}",
-                              getSwitchInfoString(), e.getMessage());
-             channel.close();
-        }
-    }
-
-
-    @Override
-    @LogMessageDoc(message="New switch connection from {ip address}",
-                   explanation="A new switch has connected from the " +
-                            "specified IP address")
-    public void channelConnected(ChannelHandlerContext ctx,
-                                 ChannelStateEvent e) throws Exception {
-        counters.switchConnected.updateCounterWithFlush();
-        channel = e.getChannel();
-        log.info("New switch connection from {}",
-                 channel.getRemoteAddress());
-        sendHandShakeMessage(OFType.HELLO);
-        setState(ChannelState.WAIT_HELLO);
-    }
-
-    @Override
-    @LogMessageDoc(message="Disconnected switch {switch information}",
-                   explanation="The specified switch has disconnected.")
-    public void channelDisconnected(ChannelHandlerContext ctx,
-                                    ChannelStateEvent e) throws Exception {
-        controller.removeSwitchChannel(this);
-        if (this.sw != null) {
-            // TODO: switchDisconnected() will check if we've previously
-            // activated the switch. Nevertheless, we might want to check
-            // here as well.
-            controller.switchDisconnected(this.sw);
-            this.sw.setConnected(false);
-        }
-
-        log.info("Disconnected switch {}", getSwitchInfoString());
-    }
-
-    @Override
-    @LogMessageDocs({
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch} due to read timeout",
-                explanation="The connected switch has failed to send any " +
-                            "messages or respond to echo requests",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch}: failed to " +
-                        "complete handshake",
-                explanation="The switch did not respond correctly " +
-                            "to handshake messages",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch} due to IO Error: {}",
-                explanation="There was an error communicating with the switch",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch} due to switch " +
-                        "state error: {error}",
-                explanation="The switch sent an unexpected message",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Disconnecting switch {switch} due to " +
-                        "message parse failure",
-                explanation="Could not parse a message from the switch",
-                recommendation=LogMessageDoc.CHECK_SWITCH),
-        @LogMessageDoc(level="ERROR",
-                message="Terminating controller due to storage exception",
-                explanation=Controller.ERROR_DATABASE,
-                recommendation=LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level="ERROR",
-                message="Could not process message: queue full",
-                explanation="OpenFlow messages are arriving faster than " +
-                            " the controller can process them.",
-                recommendation=LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level="ERROR",
-                message="Error while processing message " +
-                        "from switch {switch} {cause}",
-                explanation="An error occurred processing the switch message",
-                recommendation=LogMessageDoc.GENERIC_ACTION)
-    })
-    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
-            throws Exception {
-        if (e.getCause() instanceof ReadTimeoutException) {
-            // switch timeout
-            log.error("Disconnecting switch {} due to read timeout",
-                                 getSwitchInfoString());
-            counters.switchDisconnectReadTimeout.updateCounterWithFlush();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof HandshakeTimeoutException) {
-            log.error("Disconnecting switch {}: failed to complete handshake",
-                      getSwitchInfoString());
-            counters.switchDisconnectHandshakeTimeout.updateCounterWithFlush();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof ClosedChannelException) {
-            log.debug("Channel for sw {} already closed", getSwitchInfoString());
-        } else if (e.getCause() instanceof IOException) {
-            log.error("Disconnecting switch {} due to IO Error: {}",
-                      getSwitchInfoString(), e.getCause().getMessage());
-            if (log.isDebugEnabled()) {
-                // still print stack trace if debug is enabled
-                log.debug("StackTrace for previous Exception: ", e.getCause());
-            }
-            counters.switchDisconnectIOError.updateCounterWithFlush();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof SwitchStateException) {
-            log.error("Disconnecting switch {} due to switch state error: {}",
-                      getSwitchInfoString(), e.getCause().getMessage());
-            if (log.isDebugEnabled()) {
-                // still print stack trace if debug is enabled
-                log.debug("StackTrace for previous Exception: ", e.getCause());
-            }
-            counters.switchDisconnectSwitchStateException.updateCounterWithFlush();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof MessageParseException) {
-            log.error("Disconnecting switch "
-                                 + getSwitchInfoString() +
-                                 " due to message parse failure",
-                                 e.getCause());
-            counters.switchDisconnectParseError.updateCounterWithFlush();
-            ctx.getChannel().close();
-        } else if (e.getCause() instanceof StorageException) {
-            log.error("Terminating controller due to storage exception",
-                      e.getCause());
-            this.controller.terminate();
-        } else if (e.getCause() instanceof RejectedExecutionException) {
-            log.warn("Could not process message: queue full");
-            counters.rejectedExecutionException.updateCounterWithFlush();
-        } else {
-            log.error("Error while processing message from switch "
-                                 + getSwitchInfoString()
-                                 + "state " + this.state, e.getCause());
-            counters.switchDisconnectOtherException.updateCounterWithFlush();
-            ctx.getChannel().close();
-        }
-    }
-
-    @Override
-    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
-            throws Exception {
-        OFMessage m = BasicFactory.getInstance().getMessage(OFType.ECHO_REQUEST);
-        e.getChannel().write(Collections.singletonList(m));
-    }
-
-    @Override
-    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
-            throws Exception {
-        if (e.getMessage() instanceof List) {
-            @SuppressWarnings("unchecked")
-            List<OFMessage> msglist = (List<OFMessage>)e.getMessage();
-
-            LoadMonitor.LoadLevel loadlevel;
-            int packets_dropped = 0;
-            int packets_allowed = 0;
-            int lldps_allowed = 0;
-
-            if (this.controller.overload_drop) {
-                loadlevel = this.controller.loadmonitor.getLoadLevel();
-            }
-            else {
-                loadlevel = LoadMonitor.LoadLevel.OK;
-            }
-
-            for (OFMessage ofm : msglist) {
-                counters.messageReceived.updateCounterNoFlush();
-                // Per-switch input throttling
-                if (sw != null && sw.inputThrottled(ofm)) {
-                    counters.messageInputThrottled.updateCounterNoFlush();
-                    continue;
-                }
-                try {
-                    if (this.controller.overload_drop &&
-                        !loadlevel.equals(LoadMonitor.LoadLevel.OK)) {
-                        switch (ofm.getType()) {
-                        case PACKET_IN:
-                            switch (loadlevel) {
-                            case VERYHIGH:
-                                // Drop all packet-ins, including LLDP/BDDPs
-                                packets_dropped++;
-                                continue;
-                            case HIGH:
-                                // Drop all packet-ins, except LLDP/BDDPs
-                                byte[] data = ((OFPacketIn)ofm).getPacketData();
-                                if (data.length > 14) {
-                                    if (((data[12] == (byte)0x88) &&
-                                         (data[13] == (byte)0xcc)) ||
-                                        ((data[12] == (byte)0x89) &&
-                                         (data[13] == (byte)0x42))) {
-                                        lldps_allowed++;
-                                        packets_allowed++;
-                                        break;
-                                    }
-                                }
-                                packets_dropped++;
-                                continue;
-                            default:
-                                // Load not high, go ahead and process msg
-                                packets_allowed++;
-                                break;
-                            }
-                            break;
-                        default:
-                            // Process all non-packet-ins
-                            packets_allowed++;
-                            break;
-                        }
-                    }
-
-                    // Do the actual packet processing
-                    state.processOFMessage(this, ofm);
-
-                }
-                catch (Exception ex) {
-                    // We are the last handler in the stream, so run the
-                    // exception through the channel again by passing in
-                    // ctx.getChannel().
-                    Channels.fireExceptionCaught(ctx.getChannel(), ex);
-                }
-            }
-
-            if (loadlevel != LoadMonitor.LoadLevel.OK) {
-                if (log.isDebugEnabled()) {
-                    log.debug(
-                        "Overload: Detected {}, packets dropped={}",
-                        loadlevel.toString(), packets_dropped);
-                    log.debug(
-                        "Overload: Packets allowed={} (LLDP/BDDPs allowed={})",
-                        packets_allowed, lldps_allowed);
-                }
-            }
-            // Flush all thread local queues etc. generated by this train
-            // of messages.
-            this.controller.flushAll();
-        }
-        else {
-            Channels.fireExceptionCaught(ctx.getChannel(),
-                                         new AssertionError("Message received from Channel is not a list"));
-        }
-    }
-
-
-    /**
-     * Get a useable error string from the OFError.
-     * @param error
-     * @return
-     */
-    public static String getErrorString(OFError error) {
-        // TODO: this really should be OFError.toString. Sigh.
-        int etint = 0xffff & error.getErrorType();
-        if (etint < 0 || etint >= OFErrorType.values().length) {
-            return String.format("Unknown error type %d", etint);
-        }
-        OFErrorType et = OFErrorType.values()[etint];
-        switch (et) {
-            case OFPET_HELLO_FAILED:
-                OFHelloFailedCode hfc =
-                    OFHelloFailedCode.values()[0xffff & error.getErrorCode()];
-                return String.format("Error %s %s", et, hfc);
-            case OFPET_BAD_REQUEST:
-                OFBadRequestCode brc =
-                    OFBadRequestCode.values()[0xffff & error.getErrorCode()];
-                return String.format("Error %s %s", et, brc);
-            case OFPET_BAD_ACTION:
-                OFBadActionCode bac =
-                    OFBadActionCode.values()[0xffff & error.getErrorCode()];
-                return String.format("Error %s %s", et, bac);
-            case OFPET_FLOW_MOD_FAILED:
-                OFFlowModFailedCode fmfc =
-                    OFFlowModFailedCode.values()[0xffff & error.getErrorCode()];
-                return String.format("Error %s %s", et, fmfc);
-            case OFPET_PORT_MOD_FAILED:
-                OFPortModFailedCode pmfc =
-                    OFPortModFailedCode.values()[0xffff & error.getErrorCode()];
-                return String.format("Error %s %s", et, pmfc);
-            case OFPET_QUEUE_OP_FAILED:
-                OFQueueOpFailedCode qofc =
-                    OFQueueOpFailedCode.values()[0xffff & error.getErrorCode()];
-                return String.format("Error %s %s", et, qofc);
-            case OFPET_VENDOR_ERROR:
-                // no codes known for vendor error
-                return String.format("Error %s", et);
-        }
-        return null;
-    }
-
-    private void dispatchMessage(OFMessage m) throws IOException {
-        // handleMessage will count
-        this.controller.handleMessage(this.sw, m, null);
-    }
-
-    /**
-     * Return a string describing this switch based on the already available
-     * information (DPID and/or remote socket)
-     * @return
-     */
-    private String getSwitchInfoString() {
-        if (sw != null)
-            return sw.toString();
-        String channelString;
-        if (channel == null || channel.getRemoteAddress() == null) {
-            channelString = "?";
-        } else {
-            channelString = channel.getRemoteAddress().toString();
-        }
-        String dpidString;
-        if (featuresReply == null) {
-            dpidString = "?";
-        } else {
-            dpidString = HexString.toHexString(featuresReply.getDatapathId());
-        }
-        return String.format("[%s DPID[%s]]", channelString, dpidString);
-    }
-
-    /**
-     * Update the channels state. Only called from the state machine.
-     * TODO: enforce restricted state transitions
-     * @param state
-     */
-    private void setState(ChannelState state) {
-        this.state = state;
-    }
-
-    /**
-     * Send a message to the switch using the handshake transactions ids.
-     * @throws IOException
-     */
-    private void sendHandShakeMessage(OFType type) throws IOException {
-        // Send initial Features Request
-        OFMessage m = BasicFactory.getInstance().getMessage(type);
-        m.setXid(handshakeTransactionIds--);
-        channel.write(Collections.singletonList(m));
-    }
-
-    /**
-     * Send an setL2TableSet message to the switch.
-     */
-    private void sendHandshakeL2TableSet() {
-        OFVendor l2TableSet = (OFVendor)
-                BasicFactory.getInstance().getMessage(OFType.VENDOR);
-        l2TableSet.setXid(handshakeTransactionIds--);
-        OFBsnL2TableSetVendorData l2TableSetData =
-                new OFBsnL2TableSetVendorData(true,
-                                              controller.getCoreFlowPriority());
-        l2TableSet.setVendor(OFBigSwitchVendorData.BSN_VENDOR_ID);
-        l2TableSet.setVendorData(l2TableSetData);
-        l2TableSet.setLengthU(OFVendor.MINIMUM_LENGTH +
-                              l2TableSetData.getLength());
-        channel.write(Collections.singletonList(l2TableSet));
-    }
-
-
-    private void gotoWaitInitialRoleState() {
-        // We need to set the new state /before/ we call addSwitchChannel
-        // because addSwitchChannel will eventually call setRole
-        // which can in turn decide that the switch doesn't support
-        // roles and transition the state straight to MASTER.
-        setState(ChannelState.WAIT_INITIAL_ROLE);
-        controller.addSwitchChannelAndSendInitialRole(this);
-    }
-
-    /**
-     * Send the configuration requests to tell the switch we want full
-     * packets
-     * @throws IOException
-     */
-    private void sendHandshakeSetConfig() throws IOException {
-        List<OFMessage> msglist = new ArrayList<OFMessage>(3);
-
-        // Ensure we receive the full packet via PacketIn
-        // FIXME: We don't set the reassembly flags.
-        OFSetConfig configSet = (OFSetConfig) BasicFactory.getInstance()
-                .getMessage(OFType.SET_CONFIG);
-        configSet.setMissSendLength((short) 0xffff)
-            .setLengthU(OFSwitchConfig.MINIMUM_LENGTH);
-        configSet.setXid(handshakeTransactionIds--);
-        msglist.add(configSet);
-
-        // Barrier
-        OFBarrierRequest barrier = (OFBarrierRequest) BasicFactory.getInstance()
-                .getMessage(OFType.BARRIER_REQUEST);
-        barrier.setXid(handshakeTransactionIds--);
-        msglist.add(barrier);
-
-        // Verify (need barrier?)
-        OFGetConfigRequest configReq = (OFGetConfigRequest)
-                BasicFactory.getInstance().getMessage(OFType.GET_CONFIG_REQUEST);
-        configReq.setXid(handshakeTransactionIds--);
-        msglist.add(configReq);
-        channel.write(msglist);
-    }
-
-    /**
-     * send a description state request
-     * @throws IOException
-     */
-    private void sendHandshakeDescriptionStatsRequest() throws IOException {
-        // Get Description to set switch-specific flags
-        OFStatisticsRequest req = new OFStatisticsRequest();
-        req.setStatisticType(OFStatisticsType.DESC);
-        req.setXid(handshakeTransactionIds--);
-
-        channel.write(Collections.singletonList(req));
-    }
-
-
-    /**
-     * Read switch properties from storage and set switch attributes accordingly
-     */
-    private void readPropertyFromStorage() {
-        // At this time, also set other switch properties from storage
-        boolean is_core_switch = false;
-        IResultSet resultSet = null;
-        try {
-            String swid = sw.getStringId();
-            resultSet = this.controller.getStorageSourceService()
-                    .getRow(Controller.SWITCH_CONFIG_TABLE_NAME, swid);
-            for (Iterator<IResultSet> it =
-                    resultSet.iterator(); it.hasNext();) {
-                is_core_switch = it.next()
-                        .getBoolean(Controller.SWITCH_CONFIG_CORE_SWITCH);
-                if (log.isDebugEnabled()) {
-                    log.debug("Reading SWITCH_IS_CORE_SWITCH " +
-                            "config for switch={}, is-core={}",
-                            sw, is_core_switch);
-                }
-            }
-        }
-        finally {
-            if (resultSet != null)
-                resultSet.close();
-        }
-        if (is_core_switch) {
-            sw.setAttribute(IOFSwitch.SWITCH_IS_CORE_SWITCH,
-                            Boolean.valueOf(true));
-        }
-    }
-
-    ChannelState getStateForTesting() {
-        return state;
-    }
-
-    void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) {
-        roleChanger = new RoleChanger(roleTimeoutMs);
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFFeaturesReplyFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFFeaturesReplyFuture.java
deleted file mode 100644
index eca67bd97..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/OFFeaturesReplyFuture.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- *    Copyright 2012, Big Switch Networks, Inc. 
- * 
- *    Licensed under the Apache License, Version 2.0 (the "License"); you may
- *    not use this file except in compliance with the License. You may obtain
- *    a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- *    License for the specific language governing permissions and limitations
- *    under the License.
- **/
-
-package net.floodlightcontroller.core.internal;
-
-import java.util.concurrent.TimeUnit;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-
-import org.openflow.protocol.OFFeaturesReply;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFType;
-
-/**
- * A concrete implementation that handles asynchronously receiving
- * OFFeaturesReply
- * 
- * @author Shudong Zhou
- */
-public class OFFeaturesReplyFuture extends
-        OFMessageFuture<OFFeaturesReply> {
-
-    protected volatile boolean finished;
-
-    public OFFeaturesReplyFuture(IThreadPoolService tp,
-            IOFSwitch sw, int transactionId) {
-        super(tp, sw, OFType.FEATURES_REPLY, transactionId);
-        init();
-    }
-
-    public OFFeaturesReplyFuture(IThreadPoolService tp,
-            IOFSwitch sw, int transactionId, long timeout, TimeUnit unit) {
-        super(tp, sw, OFType.FEATURES_REPLY, transactionId, timeout, unit);
-        init();
-    }
-
-    private void init() {
-        this.finished = false;
-        this.result = null;
-    }
-
-    @Override
-    protected void handleReply(IOFSwitch sw, OFMessage msg) {
-        this.result = (OFFeaturesReply) msg;
-        this.finished = true;
-    }
-
-    @Override
-    protected boolean isFinished() {
-        return finished;
-    }
-
-    @Override
-    protected void unRegister() {
-        super.unRegister();
-        sw.cancelFeaturesReply(transactionId);
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java
deleted file mode 100644
index 25edf396c..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageDecoder.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core.internal;
-
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.handler.codec.frame.FrameDecoder;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.factory.OFMessageFactory;
-
-/**
- * Decode an openflow message from a Channel, for use in a netty
- * pipeline
- * @author readams
- */
-public class OFMessageDecoder extends FrameDecoder {
-
-    OFMessageFactory factory = BasicFactory.getInstance();
-    
-    @Override
-    protected Object decode(ChannelHandlerContext ctx, Channel channel,
-                            ChannelBuffer buffer) throws Exception {
-        if (!channel.isConnected()) {
-            // In testing, I see decode being called AFTER decode last.
-            // This check avoids that from reading curroupted frames
-            return null;
-        }
-
-        List<OFMessage> message = factory.parseMessage(buffer);
-        return message;
-    }
-
-    @Override
-    protected Object decodeLast(ChannelHandlerContext ctx, Channel channel,
-                            ChannelBuffer buffer) throws Exception {
-        // This is not strictly needed atthis time. It is used to detect
-        // connection reset detection from netty (for debug)
-        return null;
-    }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java
deleted file mode 100644
index 6be5f9a1d..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageEncoder.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core.internal;
-
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
-import org.openflow.protocol.OFMessage;
-
-/**
- * Encode an openflow message for output into a ChannelBuffer, for use in a
- * netty pipeline
- * @author readams
- */
-public class OFMessageEncoder extends OneToOneEncoder {
-
-    @Override
-    protected Object encode(ChannelHandlerContext ctx, Channel channel,
-                            Object msg) throws Exception {
-        if (!(  msg instanceof List))
-            return msg;
-
-        @SuppressWarnings("unchecked")
-        List<OFMessage> msglist = (List<OFMessage>)msg;
-        int size = 0;
-        for (OFMessage ofm :  msglist) {
-                size += ofm.getLengthU();
-        }
-
-        ChannelBuffer buf = ChannelBuffers.buffer(size);;
-        for (OFMessage ofm :  msglist) {
-            ofm.writeTo(buf);
-        }
-        return buf;
-    }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java
deleted file mode 100644
index 1fc9c1353..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/OFMessageFuture.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc.
-*    Originally created by David Erickson, Stanford University
-*
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core.internal;
-
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFType;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-
-/**
- * A Future object used to retrieve asynchronous OFMessage replies. Unregisters
- * and cancels itself by default after 60 seconds. This class is meant to be
- * sub-classed and proper behavior added to the handleReply method, and
- * termination of the Future to be handled in the isFinished method.
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public abstract class OFMessageFuture<V> implements Future<V> {
-
-    protected IThreadPoolService threadPool;
-    protected volatile boolean canceled;
-    protected CountDownLatch latch;
-    protected OFType responseType;
-    protected volatile V result;
-    protected IOFSwitch sw;
-    protected Runnable timeoutTimer;
-    protected int transactionId;
-    protected static final long DEFAULT_TIMEOUT = 60;
-    protected static final TimeUnit DEFAULT_TIMEOUT_UNIT = TimeUnit.SECONDS;
-
-    public OFMessageFuture(IThreadPoolService tp,
-            IOFSwitch sw, OFType responseType, int transactionId) {
-        this(tp, sw, responseType, transactionId,
-                 DEFAULT_TIMEOUT, DEFAULT_TIMEOUT_UNIT);
-    }
-
-    public OFMessageFuture(IThreadPoolService tp,
-            IOFSwitch sw, OFType responseType, int transactionId, long timeout, TimeUnit unit) {
-        this.threadPool = tp;
-        this.canceled = false;
-        this.latch = new CountDownLatch(1);
-        this.responseType = responseType;
-        this.sw = sw;
-        this.transactionId = transactionId;
-
-        final OFMessageFuture<V> future = this;
-        timeoutTimer = new Runnable() {
-            @Override
-            public void run() {
-                if (timeoutTimer == this)
-                    future.cancel(true);
-            }
-        };
-        threadPool.getScheduledExecutor().schedule(timeoutTimer, timeout, unit);
-    }
-
-    protected void unRegister() {
-        this.timeoutTimer = null;
-    }
-
-
-    // TODO: msg should be generic!
-    public void deliverFuture(IOFSwitch sw, OFMessage msg) {
-        if (transactionId == msg.getXid()) {
-            handleReply(sw, msg);
-            if (isFinished()) {
-                unRegister();
-                this.latch.countDown();
-            }
-        }
-    }
-
-    /**
-     * Used to handle the specific expected message this Future was reigstered
-     * for, the specified msg parameter is guaranteed to match the type and
-     * transaction id specified.
-     * @param sw
-     * @param msg
-     * @return
-     */
-    protected abstract void handleReply(IOFSwitch sw, OFMessage msg);
-
-    /**
-     * Called directly after handleReply, subclasses implement this method to
-     * indicate when the future can deregister itself from receiving future
-     * messages, and when it is safe to return the results to any waiting
-     * threads.
-     * @return when this Future has completed its work
-     */
-    protected abstract boolean isFinished();
-
-    /* (non-Javadoc)
-     * @see java.util.concurrent.Future#cancel(boolean)
-     */
-    @Override
-    public boolean cancel(boolean mayInterruptIfRunning) {
-        if (isDone()) {
-            return false;
-        } else {
-            unRegister();
-            canceled = true;
-            this.latch.countDown();
-            return !isDone();
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see java.util.concurrent.Future#isCancelled()
-     */
-    @Override
-    public boolean isCancelled() {
-        return canceled;
-    }
-
-    /* (non-Javadoc)
-     * @see java.util.concurrent.Future#isDone()
-     */
-    @Override
-    public boolean isDone() {
-        return this.latch.getCount() == 0;
-    }
-
-    /* (non-Javadoc)
-     * @see java.util.concurrent.Future#get()
-     */
-    @Override
-    public V get() throws InterruptedException, ExecutionException {
-        this.latch.await();
-        return result;
-    }
-
-    /* (non-Javadoc)
-     * @see java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit)
-     */
-    @Override
-    public V get(long timeout, TimeUnit unit) throws InterruptedException,
-            ExecutionException, TimeoutException {
-        this.latch.await(timeout, unit);
-        return result;
-    }
-
-    public int getTransactionId() {
-        return transactionId;
-    }
-
-    public void setTransactionId(int transactionId) {
-        this.transactionId = transactionId;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java b/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java
deleted file mode 100644
index 4d3f733a6..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/OFStatisticsFuture.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core.internal;
-
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.TimeUnit;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFStatisticsReply;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.statistics.OFStatistics;
-
-/**
- * A concrete implementation that handles asynchronously receiving OFStatistics
- * 
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFStatisticsFuture extends
-        OFMessageFuture<List<OFStatistics>> {
-
-    protected volatile boolean finished;
-
-    public OFStatisticsFuture(IThreadPoolService tp,
-            IOFSwitch sw, int transactionId) {
-        super(tp, sw, OFType.STATS_REPLY, transactionId);
-        init();
-    }
-
-    public OFStatisticsFuture(IThreadPoolService tp,
-            IOFSwitch sw, int transactionId, long timeout, TimeUnit unit) {
-        super(tp, sw, OFType.STATS_REPLY, transactionId, timeout, unit);
-        init();
-    }
-
-    private void init() {
-        this.finished = false;
-        this.result = new CopyOnWriteArrayList<OFStatistics>();
-    }
-
-    @Override
-    protected void handleReply(IOFSwitch sw, OFMessage msg) {
-        OFStatisticsReply sr = (OFStatisticsReply) msg;
-        synchronized (this.result) {
-            this.result.addAll(sr.getStatistics());
-            if ((sr.getFlags() & 0x1) == 0) {
-                this.finished = true;
-            }
-        }
-    }
-
-    @Override
-    protected boolean isFinished() {
-        return finished;
-    }
-    
-    @Override
-    protected void unRegister() {
-        super.unRegister();
-        sw.cancelStatisticsReply(transactionId);
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java
new file mode 100644
index 000000000..ddfd00872
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchAppHandshakePlugin.java
@@ -0,0 +1,116 @@
+package net.floodlightcontroller.core.internal;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.Timer;
+import org.jboss.netty.util.TimerTask;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitAppHandshakeState;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * This class is a plugin that can be used by applications to tap into the
+ * switch handshake. It operates much like the switch handshake. Messages should
+ * be sent upon entering the plugin and OF response messages should be handled
+ * just like any part of the switch handshake.
+ *
+ * @author Jason Parraga <jason.parraga@bigswitch.com>
+ */
+public abstract class OFSwitchAppHandshakePlugin {
+
+    private static final Logger log = LoggerFactory.getLogger(OFSwitchAppHandshakePlugin.class);
+
+    private WaitAppHandshakeState state;
+    @edu.umd.cs.findbugs.annotations.SuppressWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    private IOFSwitch sw;
+    private volatile Timeout timeout;
+
+    private final PluginResult defaultResult;
+    private final int timeoutS;
+
+    /**
+     * Constructor for OFSwitchAppHandshakePlugin
+     * @param defaultResult the default result in the event of a timeout
+     * @param defaultTimeoutS the timeout length in seconds
+     */
+    protected OFSwitchAppHandshakePlugin(PluginResult defaultResult, int timeoutS){
+        Preconditions.checkNotNull(defaultResult, "defaultResult");
+        Preconditions.checkNotNull(timeoutS, "timeoutS");
+
+        this.defaultResult = defaultResult;
+        this.timeoutS = timeoutS;
+    }
+
+    /**
+     * Process incoming OF Messages
+     *
+     * @param m The OF Message received
+     */
+    protected abstract void processOFMessage(OFMessage m);
+
+    /**
+     * Enter this plugin. Should be used to send messages.
+     */
+    protected abstract void enterPlugin();
+
+    /**
+     * Gets the switch associated with the handshake for use by the plugin
+     * writer.
+     *
+     * @return the switch associated with the handshake.
+     */
+    protected IOFSwitch getSwitch() {
+        return this.sw;
+    }
+
+    /**
+     * Initialization for plugin called by the OFSwitchHandshakeHandler
+     *
+     * @param state the current state of the OFSwitchHandshakeHandler
+     * @param sw the current switch of the OFSwitchHandshakeHandler
+     */
+    final void init(WaitAppHandshakeState state, IOFSwitch sw, Timer timer) {
+        this.state = state;
+        this.sw = sw;
+        this.timeout = timer.newTimeout(new PluginTimeoutTask(), timeoutS, TimeUnit.SECONDS);
+    }
+
+    /**
+     * Called to denote that the plugin has finished
+     *
+     * @param result
+     *            the result of the plugin in regards to handshaking
+     */
+    protected final void exitPlugin(PluginResult result) {
+        timeout.cancel();
+        state.exitPlugin(result);
+    }
+
+    /**
+     * Plugin timeout task that will exit the plugin
+     * with the default result value when timed out.
+     *
+     */
+    private final class PluginTimeoutTask implements TimerTask {
+
+        @Override
+        public void run(Timeout timeout) throws Exception {
+            if (!timeout.isCancelled()) {
+                log.warn("App handshake plugin for {} timed out. Returning result {}.",
+                         sw, defaultResult);
+                exitPlugin(defaultResult);
+            }
+        }
+    }
+
+    public enum PluginResultType {
+        CONTINUE(),
+        DISCONNECT(),
+        QUARANTINE();
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
new file mode 100644
index 000000000..90c7d4654
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandler.java
@@ -0,0 +1,1886 @@
+package net.floodlightcontroller.core.internal;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
+
+import org.jboss.netty.util.Timer;
+import net.floodlightcontroller.core.GenTableMap;
+import net.floodlightcontroller.core.HARole;
+import net.floodlightcontroller.core.IOFConnection;
+import net.floodlightcontroller.core.IOFConnectionBackend;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IOFSwitch.SwitchStatus;
+import net.floodlightcontroller.core.IOFSwitchBackend;
+import net.floodlightcontroller.core.PortChangeEvent;
+import net.floodlightcontroller.core.SwitchDescription;
+import net.floodlightcontroller.core.annotations.LogMessageDoc;
+import net.floodlightcontroller.core.annotations.LogMessageDocs;
+import net.floodlightcontroller.core.internal.OFSwitchAppHandshakePlugin.PluginResultType;
+import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
+import org.projectfloodlight.openflow.protocol.OFBarrierReply;
+import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
+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.OFBsnSetL2TableRequest;
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFDescStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFErrorType;
+import org.projectfloodlight.openflow.protocol.OFExperimenter;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFFlowModFailedCode;
+import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
+import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
+import org.projectfloodlight.openflow.protocol.OFGetConfigRequest;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleRequest;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
+import org.projectfloodlight.openflow.protocol.OFQueueGetConfigReply;
+import org.projectfloodlight.openflow.protocol.OFRoleReply;
+import org.projectfloodlight.openflow.protocol.OFRoleRequest;
+import org.projectfloodlight.openflow.protocol.OFSetConfig;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
+import org.projectfloodlight.openflow.protocol.OFStatsRequestFlags;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
+import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFAuxId;
+import org.projectfloodlight.openflow.types.U64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Switch handler deals with the switch connection and dispatches
+ * switch messages to the appropriate locations. These messages
+ * are typically received by the channel handler first and piped here.
+ *
+ * @author Jason Parraga <jason.parraga@bigswitch.com>
+ */
+public class OFSwitchHandshakeHandler implements IOFConnectionListener {
+    private static final Logger log = LoggerFactory.getLogger(OFSwitchHandshakeHandler.class);
+
+    private final IOFSwitchManager switchManager;
+    private final RoleManager roleManager;
+    private final IOFConnectionBackend mainConnection;
+    private final SwitchManagerCounters switchManagerCounters;
+    private IOFSwitchBackend sw;
+    private final Map<OFAuxId, IOFConnectionBackend> auxConnections;
+    private volatile OFSwitchHandshakeState state;
+    private RoleChanger roleChanger;
+    // Default to 1.3 - This is overwritten by the features reply
+    private OFFactory factory = OFFactories.getFactory(OFVersion.OF_13);
+    private final OFFeaturesReply featuresReply;
+    private final Timer timer;
+
+    private final ArrayList<OFPortStatus> pendingPortStatusMsg;
+
+    /** transaction Ids to use during handshake. Since only one thread
+     * calls into the OFChannelHandler we don't need atomic.
+     * We will count down
+     */
+    private long handshakeTransactionIds = 0x00FFFFFFFFL;
+
+    /* Exponential backoff of master role assertion */
+    private final long MAX_ASSERT_TIME_INTERVAL_NS = TimeUnit.SECONDS.toNanos(120);
+    private final long DEFAULT_ROLE_TIMEOUT_NS = TimeUnit.SECONDS.toNanos(10);
+
+    protected OFPortDescStatsReply portDescStats;
+
+    /**
+     * When we remove a pending role request and set the role on the switch
+     * we use this enum to indicate how we arrived at the decision.
+     * @author gregor
+     */
+    private enum RoleRecvStatus {
+        /** We received a role reply message from the switch */
+        RECEIVED_REPLY,
+        /** The switch returned an error indicated that roles are not
+         * supported*/
+        UNSUPPORTED,
+        /** The request timed out */
+        NO_REPLY;
+    }
+    /**
+     * A utility class to handle role requests and replies for this channel.
+     * After a role request is submitted the role changer keeps track of the
+     * pending request, collects the reply (if any) and times out the request
+     * if necessary.
+     *
+     * To simplify role handling we only keep track of the /last/ pending
+     * role reply send to the switch. If multiple requests are pending and
+     * we receive replies for earlier requests we ignore them. However, this
+     * way of handling pending requests implies that we could wait forever if
+     * a new request is submitted before the timeout triggers. If necessary
+     * we could work around that though.
+     * @author gregor
+     */
+    private class RoleChanger {
+        // indicates that a request is currently pending
+        // needs to be volatile to allow correct double-check idiom
+        private volatile boolean requestPending;
+        // the transaction Id of the pending request
+        private long pendingXid;
+        // the role that's pending
+        private OFControllerRole pendingRole;
+        // system time in NS when we send the request
+        private long roleSubmitTimeNs;
+        // the timeout to use
+        private final long roleTimeoutNs;
+        private long lastAssertTimeNs;
+        private long assertTimeIntervalNs = TimeUnit.SECONDS.toNanos(1);
+
+        public RoleChanger(long roleTimeoutNs) {
+            this.roleTimeoutNs = roleTimeoutNs;
+            // System.nanoTime() may be negative -- prime the roleSubmitTime as
+            // "long ago in the past" to be robust against it.
+            this.roleSubmitTimeNs = System.nanoTime() - (2 * roleTimeoutNs);
+            this.lastAssertTimeNs = System.nanoTime() - (2 * assertTimeIntervalNs);
+            this.requestPending = false;
+            this.pendingXid = -1;
+            this.pendingRole = null;
+        }
+
+        /**
+         * Send Nicira role request message to the switch requesting the
+         * specified role.
+         *
+         * @param role role to request
+         */
+        private long sendNiciraRoleRequest(OFControllerRole role){
+
+            long xid;
+            // Construct the role request message
+            if(factory.getVersion().compareTo(OFVersion.OF_12) < 0) {
+                OFNiciraControllerRoleRequest.Builder builder =
+                        factory.buildNiciraControllerRoleRequest();
+                xid = factory.nextXid();
+                builder.setXid(xid);
+
+                OFNiciraControllerRole niciraRole = NiciraRoleUtils.ofRoleToNiciraRole(role);
+                builder.setRole(niciraRole);
+                OFNiciraControllerRoleRequest roleRequest = builder.build();
+                // Send it to the switch
+                mainConnection.write(roleRequest);
+            } else {
+                // send an OF 1.2+ role request
+                OFRoleRequest roleRequest = factory.buildRoleRequest()
+                        // we don't use the generation id scheme for now,
+                        // switch initializes to 0, we keep it at 0
+                        .setGenerationId(U64.of(0))
+                        .setRole(role)
+                        .build();
+                xid = roleRequest.getXid();
+                mainConnection.write(roleRequest);
+            }
+            return xid;
+        }
+
+        /**
+         * Send a role request for the given role only if no other role
+         * request is currently pending.
+         * @param role The role to send to the switch.
+         * @throws IOException
+         */
+        @LogMessageDoc(level="WARN",
+                message="Reasserting master role on switch {SWITCH}, " +
+                        "likely a configruation error with multiple masters",
+                explanation="The controller keeps getting permission error " +
+                        "from switch, likely due to switch connected to another " +
+                        "controller also in master mode",
+                        recommendation=LogMessageDoc.CHECK_SWITCH)
+        synchronized void sendRoleRequestIfNotPending(OFControllerRole role)
+                throws IOException {
+            long now = System.nanoTime();
+            if (now - lastAssertTimeNs < assertTimeIntervalNs) {
+                return;
+            }
+
+            lastAssertTimeNs = now;
+            if (assertTimeIntervalNs < MAX_ASSERT_TIME_INTERVAL_NS) { // 2 minutes max
+                assertTimeIntervalNs <<= 1;
+            } else if (role == OFControllerRole.ROLE_MASTER){
+                log.warn("Reasserting master role on switch {}, " +
+                        "likely a switch config error with multiple masters",
+                        role, sw);
+            }
+            if (!requestPending)
+                sendRoleRequest(role);
+            else
+                switchManagerCounters.roleNotResentBecauseRolePending.increment();
+        }
+
+        /**
+         * Send a role request with the given role to the switch.
+         *
+         * Send a role request with the given role to the switch and update
+         * the pending request and timestamp.
+         *
+         * @param role
+         * @throws IOException
+         */
+        synchronized void sendRoleRequest(OFControllerRole role) throws IOException {
+            /*
+             * There are three cases to consider for SUPPORTS_NX_ROLE:
+             *
+             * 1) unset. We have neither received a role reply from the
+             *    switch nor has a request timed out. Send a request.
+             * 2) TRUE: We've already send a request earlier and received
+             *    a reply. The switch supports role and we should send one.
+             * 3) FALSE: We have already send a role and received an error.
+             *    The switch does not support roles. Don't send a role request,
+             *    set the switch's role directly.
+             */
+            Boolean supportsNxRole = (Boolean)
+                    sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE);
+            if ((supportsNxRole != null) && !supportsNxRole) {
+                setSwitchRole(role, RoleRecvStatus.UNSUPPORTED);
+            } else {
+                pendingXid = sendNiciraRoleRequest(role);
+                pendingRole = role;
+                this.roleSubmitTimeNs = System.nanoTime();
+                requestPending = true;
+            }
+        }
+
+        /**
+         * Deliver a received role reply and set SWITCH_SUPPORTS_NX_ROLE.
+         *
+         * Check if a request is pending and if the received reply matches the
+         * the expected pending reply (we check both role and xid) we set
+         * the role for the switch/channel.
+         *
+         * If a request is pending but doesn't match the reply we ignore it.
+         *
+         * If no request is pending we disconnect.
+         *
+         * @param xid
+         * @param role
+         * @throws SwitchStateException if no request is pending
+         */
+        synchronized void deliverRoleReply(long xid, OFControllerRole role) {
+            if (!requestPending) {
+                // Maybe don't disconnect if the role reply we received is
+                // for the same role we are already in.
+                String msg = String.format("Switch: [%s], State: [%s], "
+                                + "received unexpected RoleReply[%s]. "
+                                + "No roles are pending",
+                                OFSwitchHandshakeHandler.this.getSwitchInfoString(),
+                                OFSwitchHandshakeHandler.this.state.toString(),
+                                role);
+                throw new SwitchStateException(msg);
+            }
+
+            if (pendingXid == xid && pendingRole == role) {
+                log.debug("[{}] Received role reply message setting role to {}",
+                          getDpid(), role);
+                switchManagerCounters.roleReplyReceived.increment();
+                setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY);
+            } else {
+                log.debug("[{}] Received stale or unexpected role reply " +
+                          "{}, xid={}. Ignoring. " +
+                          "Waiting for {}, xid={}",
+                          new Object[] { getDpid(), role, xid,
+                                         pendingRole, pendingXid });
+            }
+        }
+
+        /**
+         * Called if we receive an  error message. If the xid matches the
+         * pending request we handle it otherwise we ignore it. We also
+         * set SWITCH_SUPPORTS_NX_ROLE to false.
+         *
+         * Note: since we only keep the last pending request we might get
+         * error messages for earlier role requests that we won't be able
+         * to handle
+         * @param xid
+         * @return true if the error was handled by us, false otherwise
+         * @throws SwitchStateException if the error was for the pending
+         * role request but was unexpected
+         */
+        synchronized boolean deliverError(OFErrorMsg error) {
+            if (!requestPending)
+                return false;
+
+            if (pendingXid == error.getXid()) {
+                if (error.getErrType() == OFErrorType.BAD_REQUEST) {
+                    switchManagerCounters.roleReplyErrorUnsupported.increment();
+                    setSwitchRole(pendingRole, RoleRecvStatus.UNSUPPORTED);
+                } else {
+                    // TODO: Is this the right thing to do if we receive
+                    // some other error besides a bad request error?
+                    // Presumably that means the switch did actually
+                    // understand the role request message, but there
+                    // was some other error from processing the message.
+                    // OF 1.2 specifies a ROLE_REQUEST_FAILED
+                    // error code, but it doesn't look like the Nicira
+                    // role request has that. Should check OVS source
+                    // code to see if it's possible for any other errors
+                    // to be returned.
+                    // If we received an error the switch is not
+                    // in the correct role, so we need to disconnect it.
+                    // We could also resend the request but then we need to
+                    // check if there are other pending request in which
+                    // case we shouldn't resend. If we do resend we need
+                    // to make sure that the switch eventually accepts one
+                    // of our requests or disconnect the switch. This feels
+                    // cumbersome.
+                    String msg = String.format("Switch: [%s], State: [%s], "
+                                    + "Unexpected error %s in respone to our "
+                                    + "role request for %s.",
+                                    OFSwitchHandshakeHandler.this.getSwitchInfoString(),
+                                    OFSwitchHandshakeHandler.this.state.toString(),
+                                    error.toString(),
+                                    pendingRole);
+                    throw new SwitchStateException(msg);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        /**
+         * Check if a pending role request has timed out.
+         */
+        void checkTimeout() {
+            if (!requestPending)
+                return;
+            synchronized(this) {
+                if (!requestPending)
+                    return;
+                long now = System.nanoTime();
+                if (now - this.roleSubmitTimeNs > roleTimeoutNs) {
+                    // timeout triggered.
+                    switchManagerCounters.roleReplyTimeout.increment();
+                    setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY);
+                }
+            }
+        }
+
+        /**
+         * Set the role for this switch / channel.
+         *
+         * If the status indicates that we received a reply we set the role.
+         * If the status indicates otherwise we disconnect the switch if
+         * the role is SLAVE.
+         *
+         * "Setting a role" means setting the appropriate ChannelState,
+         * setting the flags on the switch and
+         * notifying Controller.java about new role of the switch
+         *
+         * @param role The role to set.
+         * @param status How we derived at the decision to set this status.
+         */
+        synchronized private void setSwitchRole(OFControllerRole role, RoleRecvStatus status) {
+            requestPending = false;
+            if (status == RoleRecvStatus.RECEIVED_REPLY)
+                sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true);
+            else
+                sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
+            sw.setControllerRole(role);
+
+            if (role != OFControllerRole.ROLE_SLAVE) {
+                OFSwitchHandshakeHandler.this.setState(new MasterState());
+            } else {
+                if (status != RoleRecvStatus.RECEIVED_REPLY) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Disconnecting switch {}. Doesn't support role"
+                              + "({}) request and controller is now SLAVE",
+                              getSwitchInfoString(), status);
+                    }
+                    // the disconnect will trigger a switch removed to
+                    // controller so no need to signal anything else
+                    sw.disconnect();
+                } else {
+                    OFSwitchHandshakeHandler.this.setState(new SlaveState());
+                }
+            }
+        }
+    }
+
+    /**
+     * Default implementation for message handlers in any state.
+     *
+     * Individual states must override these if they want a behavior
+     * that differs from the default.
+     *
+     * In general, these handlers simply ignore the message and do
+     * nothing.
+     *
+     * There are some exceptions though, since some messages really
+     * are handled the same way in every state (e.g., ECHO_REQUST) or
+     * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY
+     */
+    public abstract class OFSwitchHandshakeState {
+
+        void processOFBarrierReply(OFBarrierReply m) {
+            // do nothing
+        }
+
+        void processOFError(OFErrorMsg m) {
+            logErrorDisconnect(m);
+        }
+
+        void processOFFlowRemoved(OFFlowRemoved m) {
+            unhandledMessageReceived(m);
+        }
+
+        void processOFGetConfigReply(OFGetConfigReply m) {
+            // we only expect config replies in the WAIT_CONFIG_REPLY state
+            // TODO: might use two different strategies depending on whether
+            // we got a miss length of 64k or not.
+            illegalMessageReceived(m);
+        }
+
+        void processOFPacketIn(OFPacketIn m) {
+            unhandledMessageReceived(m);
+        }
+
+        // By default add port status messages to a pending list
+        void processOFPortStatus(OFPortStatus m) {
+            pendingPortStatusMsg.add(m);
+        }
+
+        void processOFQueueGetConfigReply(OFQueueGetConfigReply m) {
+            unhandledMessageReceived(m);
+        }
+
+        void processOFStatsReply(OFStatsReply m) {
+            switch(m.getStatsType()) {
+                case PORT_DESC:
+                    processPortDescStatsReply((OFPortDescStatsReply) m);
+                    break;
+                default:
+                    unhandledMessageReceived(m);
+            }
+        }
+
+        void processOFExperimenter(OFExperimenter m) {
+            if (m instanceof OFBsnControllerConnectionsReply) {
+                OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
+                handleControllerConnectionMessage(reply);
+            } else {
+                unhandledMessageReceived(m);
+            }
+        }
+
+        void processPortDescStatsReply(OFPortDescStatsReply m) {
+            unhandledMessageReceived(m);
+        }
+
+        void processOFRoleReply(OFRoleReply m) {
+            unhandledMessageReceived(m);
+        }
+
+        private final boolean handshakeComplete;
+        OFSwitchHandshakeState(boolean handshakeComplete) {
+            this.handshakeComplete = handshakeComplete;
+        }
+
+        void logState() {
+            if(log.isDebugEnabled())
+                log.debug("[{}] - Switch Handshake - enter state {}", mainConnection.getDatapathId(), this.getClass().getSimpleName());
+        }
+
+        /** enter this state. Can initialize the handler, send
+         *  the necessary messages, etc.
+         */
+         void enterState(){
+         }
+
+        /**
+         * Is this a state in which the handshake has completed?
+         * @return true if the handshake is complete
+         */
+        public boolean isHandshakeComplete() {
+            return handshakeComplete;
+        }
+
+        /**
+         * Used to notify the WAIT OF AUX state that
+         * a new connection has been added
+         * @param connection
+         */
+        public void auxConnectionOpened(IOFConnectionBackend connection) {
+            // Should only be handled in wait of aux
+            log.debug("[{}] - Switch Handshake - unhandled aux connection event",
+                    getDpid());
+        }
+        /**
+         * Get a string specifying the switch connection, state, and
+         * message received. To be used as message for SwitchStateException
+         * or log messages
+         * @param h The channel handler (to get switch information_
+         * @param m The OFMessage that has just been received
+         * @param details A string giving more details about the exact nature
+         * of the problem.
+         * @return
+         */
+        // needs to be protected because enum members are acutally subclasses
+        protected String getSwitchStateMessage(OFMessage m,
+                                                      String details) {
+            return String.format("Switch: [%s], State: [%s], received: [%s]"
+                                 + ", details: %s",
+                                 getSwitchInfoString(),
+                                 this.toString(),
+                                 m.getType().toString(),
+                                 details);
+        }
+
+        /**
+         * We have an OFMessage we didn't expect given the current state and
+         * we want to treat this as an error.
+         * We currently throw an exception that will terminate the connection
+         * However, we could be more forgiving
+         * @param h the channel handler that received the message
+         * @param m the message
+         * @throws SwitchStateExeption we always through the execption
+         */
+        // needs to be protected because enum members are acutally subclasses
+        protected void illegalMessageReceived(OFMessage m) {
+            String msg = getSwitchStateMessage(m,
+                    "Switch should never send this message in the current state");
+            throw new SwitchStateException(msg);
+
+        }
+
+        /**
+         * We have an OFMessage we didn't expect given the current state and
+         * we want to ignore the message
+         * @param h the channel handler the received the message
+         * @param m the message
+         */
+        protected void unhandledMessageReceived(OFMessage m) {
+            switchManagerCounters.unhandledMessage.increment();
+            if (log.isDebugEnabled()) {
+                String msg = getSwitchStateMessage(m,
+                        "Ignoring unexpected message");
+                log.debug(msg);
+            }
+        }
+
+        /**
+         * Log an OpenFlow error message from a switch
+         * @param error The error message
+         */
+        @LogMessageDoc(level="ERROR",
+                message="Error {error type} {error code} from {switch} " +
+                        "in state {state}",
+                explanation="The switch responded with an unexpected error" +
+                        "to an OpenFlow message from the controller",
+                recommendation="This could indicate improper network operation. " +
+                        "If the problem persists restarting the switch and " +
+                        "controller may help."
+                )
+        protected void logError(OFErrorMsg error) {
+            log.error("{} from switch {} in state {}",
+                      new Object[] {
+                          error.toString(),
+                          getSwitchInfoString(),
+                          this.toString()});
+        }
+
+        /**
+         * Log an OpenFlow error message from a switch and disconnect the
+         * channel
+         * @param error The error message
+         */
+        protected void logErrorDisconnect(OFErrorMsg error) {
+            logError(error);
+            mainConnection.disconnect();
+        }
+
+        /**
+         * Extract the role from an OFVendor message.
+         *
+         * Extract the role from an OFVendor message if the message is a
+         * Nicira role reply. Otherwise return null.
+         *
+         * @param h The channel handler receiving the message
+         * @param vendorMessage The vendor message to parse.
+         * @return The role in the message if the message is a Nicira role
+         * reply, null otherwise.
+         */
+        protected OFControllerRole extractNiciraRoleReply(OFMessage vendorMessage) {
+            if (!(vendorMessage instanceof OFNiciraControllerRoleReply))
+                return null;
+            OFNiciraControllerRoleReply roleReply =
+                    (OFNiciraControllerRoleReply) vendorMessage;
+            return NiciraRoleUtils.niciraToOFRole(roleReply);
+        }
+
+        /**
+         * Handle a port status message.
+         *
+         * Handle a port status message by updating the port maps in the
+         * IOFSwitch instance and notifying Controller about the change so
+         * it can dispatch a switch update.
+         *
+         * @param h The OFChannelHhandler that received the message
+         * @param m The PortStatus message we received
+         * @param doNotify if true switch port changed events will be
+         * dispatched
+         */
+        protected void handlePortStatusMessage(OFPortStatus m,
+                                               boolean doNotify) {
+            if (sw == null) {
+                String msg = getSwitchStateMessage(m,
+                        "State machine error: switch is null. Should never " +
+                        "happen");
+                throw new SwitchStateException(msg);
+            }
+            Collection<PortChangeEvent> changes = sw.processOFPortStatus(m);
+            if (doNotify) {
+                for (PortChangeEvent ev: changes)
+                    switchManager.notifyPortChanged(sw, ev.port, ev.type);
+            }
+        }
+
+        protected void handleControllerConnectionMessage(OFBsnControllerConnectionsReply m) {
+            if (sw == null) {
+                String msg = getSwitchStateMessage(m,
+                        "State machine error: switch is null. Should never " +
+                        "happen");
+                throw new SwitchStateException(msg);
+            }
+            // Update switches
+            sw.updateControllerConnections(m);
+            // Notify role manager
+            roleManager.notifyControllerConnectionUpdate();
+        }
+
+
+        /**
+         * Process an OF message received on the channel and
+         * update state accordingly.
+         *
+         * The main "event" of the state machine. Process the received message,
+         * send follow up message if required and update state if required.
+         *
+         * Switches on the message type and calls more specific event handlers
+         * for each individual OF message type. If we receive a message that
+         * is supposed to be sent from a controller to a switch we throw
+         * a SwitchStateExeption.
+         *
+         * The more specific handlers can also throw SwitchStateExceptions
+         *
+         * @param h The OFChannelHandler that received the message
+         * @param m The message we received.
+         * @throws SwitchStateException
+         * @throws IOException
+         */
+        void processOFMessage(OFMessage m) {
+            roleChanger.checkTimeout();
+            switch(m.getType()) {
+                case BARRIER_REPLY:
+                    processOFBarrierReply((OFBarrierReply)m);
+                    break;
+                case ERROR:
+                    processOFError((OFErrorMsg)m);
+                    break;
+                case FLOW_REMOVED:
+                    processOFFlowRemoved((OFFlowRemoved)m);
+                    break;
+                case GET_CONFIG_REPLY:
+                    processOFGetConfigReply((OFGetConfigReply)m);
+                    break;
+                case PACKET_IN:
+                    processOFPacketIn((OFPacketIn)m);
+                    break;
+                case PORT_STATUS:
+                    processOFPortStatus((OFPortStatus)m);
+                    break;
+                case QUEUE_GET_CONFIG_REPLY:
+                    processOFQueueGetConfigReply((OFQueueGetConfigReply)m);
+                    break;
+                case STATS_REPLY:
+                    processOFStatsReply((OFStatsReply)m);
+                    break;
+                case ROLE_REPLY:
+                    processOFRoleReply((OFRoleReply)m);
+                    break;
+                case EXPERIMENTER:
+                    processOFExperimenter((OFExperimenter)m);
+                    break;
+                default:
+                    illegalMessageReceived(m);
+                    break;
+            }
+        }
+    }
+
+        /**
+         * Initial state before channel is connected. Should not handle any messages.
+         */
+          public class InitState extends OFSwitchHandshakeState {
+
+            InitState() {
+                super(false);
+            }
+
+            @Override
+            public void logState() {
+                log.debug("[{}] - Switch Handshake - Initiating from {}",
+                        getDpid(), mainConnection.getRemoteInetAddress());
+            }
+        }
+
+        /**
+         * We are waiting for a features reply message. Once we receive it
+         * we send a SetConfig request, barrier, and GetConfig request.
+         * Next stats is WAIT_CONFIG_REPLY or WAIT_SET_L2_TABLE_REPLY
+         */
+        public class WaitPortDescStatsReplyState extends OFSwitchHandshakeState {
+            WaitPortDescStatsReplyState() {
+                super(false);
+            }
+
+            @Override
+            void enterState(){
+                sendPortDescRequest();
+            }
+
+            @Override
+            void processPortDescStatsReply(OFPortDescStatsReply  m) {
+                portDescStats = m;
+
+                setState(new WaitConfigReplyState());
+            }
+
+            @Override
+            void processOFExperimenter(OFExperimenter m) {
+                unhandledMessageReceived(m);
+            }
+        }
+
+        public class WaitSetL2TableReplyState extends OFSwitchHandshakeState {
+
+            WaitSetL2TableReplyState() {
+                super(false);
+            }
+
+            @Override
+            void processOFExperimenter(OFExperimenter m) {
+                // TODO: actually parse the response
+                setState(new WaitConfigReplyState());
+            };
+
+            @Override
+            void processOFStatsReply(OFStatsReply  m) {
+                illegalMessageReceived(m);
+            }
+        }
+
+        /**
+         * We are waiting for a config reply message. Once we receive it
+         * we send a DescriptionStatsRequest to the switch.
+         * Next state: WAIT_DESCRIPTION_STAT_REPLY
+         */
+        public class WaitConfigReplyState extends OFSwitchHandshakeState {
+
+            WaitConfigReplyState() {
+                super(false);
+            }
+
+            @Override
+            @LogMessageDocs({
+                @LogMessageDoc(level="WARN",
+                        message="Config Reply from {switch} has " +
+                                "miss length set to {length}",
+                        explanation="The controller requires that the switch " +
+                                "use a miss length of 0xffff for correct " +
+                                "function",
+                        recommendation="Use a different switch to ensure " +
+                                "correct function")
+            })
+            void processOFGetConfigReply(OFGetConfigReply m) {
+                if (m.getMissSendLen() == 0xffff) {
+                    log.trace("Config Reply from switch {} confirms "
+                            + "miss length set to 0xffff",
+                            getSwitchInfoString());
+                } else {
+                    // FIXME: we can't really deal with switches that don't send
+                    // full packets. Shouldn't we drop the connection here?
+                    // FIXME: count??
+                    log.warn("Config Reply from switch {} has"
+                            + "miss length set to {}",
+                            getSwitchInfoString(),
+                            m.getMissSendLen());
+                }
+                setState(new WaitDescriptionStatReplyState());
+            }
+
+            @Override
+            void processOFStatsReply(OFStatsReply  m) {
+                illegalMessageReceived(m);
+            }
+
+            @Override
+            void processOFError(OFErrorMsg m) {
+                if ((m.getErrType() == OFErrorType.BAD_REQUEST) &&
+                        (((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.BAD_EXPERIMENTER)) {
+                    log.debug("Switch {} has multiple tables but does not " +
+                            "support L2 table extension",
+                            getSwitchInfoString());
+                    return;
+                }
+                logErrorDisconnect(m);
+            }
+
+            @Override
+            void enterState() {
+                sendHandshakeSetConfig();
+            }
+        }
+
+        /**
+         * We are waiting for a OFDescriptionStat message from the switch.
+         * Once we receive any stat message we try to parse it. If it's not
+         * a description stats message we disconnect. If its the expected
+         * description stats message, we:
+         *    - use the switch driver to bind the switch and get an IOFSwitch
+         *      instance, setup the switch instance
+         *    - setup the IOFSwitch instance
+         *    - add switch to FloodlightProvider and send the intial role
+         *      request to the switch.
+         *
+         * Next state: WaitOFAuxCxnsReplyState (if OF1.3), else
+         *     WaitInitialRoleState or WaitSwitchDriverSubHandshake
+         *
+         * All following states will have a h.sw instance!
+         */
+        public class WaitDescriptionStatReplyState extends OFSwitchHandshakeState{
+
+            WaitDescriptionStatReplyState() {
+                super(false);
+            }
+
+            @LogMessageDoc(message="Switch {switch info} bound to class " +
+                "{switch driver}, description {switch description}",
+                    explanation="The specified switch has been bound to " +
+                            "a switch driver based on the switch description" +
+                            "received from the switch")
+            @Override
+            void processOFStatsReply(OFStatsReply m) {
+                // Read description, if it has been updated
+                if (m.getStatsType() != OFStatsType.DESC) {
+                    illegalMessageReceived(m);
+                    return;
+                }
+
+                OFDescStatsReply descStatsReply = (OFDescStatsReply) m;
+                SwitchDescription description = new SwitchDescription(descStatsReply);
+                sw = switchManager.getOFSwitchInstance(mainConnection, description, factory, featuresReply.getDatapathId());
+                switchManager.switchAdded(sw);
+                // set switch information
+                // set features reply and channel first so we a DPID and
+                // channel info.
+                sw.setFeaturesReply(featuresReply);
+                if(portDescStats != null) {
+                    sw.setPortDescStats(portDescStats);
+                }
+
+                // Handle pending messages now that we have a sw object
+                handlePendingPortStatusMessages(description);
+
+                // Handle non OF 13 connections
+                if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){
+                    sw.startDriverHandshake();
+                    if (sw.isDriverHandshakeComplete()) {
+                        setState(new WaitAppHandshakeState());
+                    } else {
+                        setState(new WaitSwitchDriverSubHandshakeState());
+                    }
+                }
+                // Handle OF 1.3 MAIN Connection
+                else{
+                    setState(new WaitOFAuxCxnsReplyState());
+                }
+            }
+
+            void handlePendingPortStatusMessages(SwitchDescription description){
+                for (OFPortStatus ps: pendingPortStatusMsg)
+                    handlePortStatusMessage(ps, false);
+                pendingPortStatusMsg.clear();
+                log.info("Switch {} bound to class {}," +
+                        " description {}",
+                         new Object[] { sw, sw.getClass(),
+                                    description });
+            }
+
+            @Override
+            void enterState() {
+                sendHandshakeDescriptionStatsRequest();
+            }
+        }
+
+        /**
+         * We are waiting for an OFAuxCxnsReply message from the switch.
+         *  If the switch replies with a status of 0 it has approved of our request.
+         *  If the auxiliary connections haven't already connected we will
+         *  wait for them.
+         *
+         * Next state: WAIT_GENTABLE_DESC_STATS_REPLY (if OF1.3), else
+         *     WAIT_INITIAL_ROLE or WAIT_SWITCH_DRIVER_SUB_HANDSHAKE
+         *
+         * All following states will have a h.sw instance!
+         */
+        public class WaitOFAuxCxnsReplyState extends OFSwitchHandshakeState {
+
+            // Default number of aux connections
+            int numAux = 0;
+
+            WaitOFAuxCxnsReplyState() {
+                super(false);
+            }
+
+            @Override
+            void processOFExperimenter(OFExperimenter m) {
+               if(m instanceof OFBsnSetAuxCxnsReply){
+                   OFBsnSetAuxCxnsReply auxReply = (OFBsnSetAuxCxnsReply) m;
+
+                   if(auxReply.getStatus() == 0){
+                       if(this.numAux != 0){
+                           // All aux connections havent arrived yet
+                           if(auxConnections.size() != this.numAux){
+                               // We do nothing and wait for connections...
+                           } else {
+                               // Looks like all the aux connections have already arrived
+                               gotoNextState();
+                           }
+                       }
+                       else {
+                           // We don't need any OF Aux Connections
+                           gotoNextState();
+                       }
+                   } else {
+                       String msg = String.format("Switch: [%s], HandshakeState: [%s], "
+                               + "received unexpected OF Aux Status [%s]. ",
+                               OFSwitchHandshakeHandler.this.getSwitchInfoString(),
+                               OFSwitchHandshakeHandler.this.state.toString(),
+                               String.valueOf(auxReply.getStatus()));
+                       throw new OFAuxException(msg);
+                   }
+               } else if(m instanceof OFBsnControllerConnectionsReply) {
+                   OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
+                   handleControllerConnectionMessage(reply);
+               }
+            }
+
+            @Override
+            public void auxConnectionOpened(IOFConnectionBackend auxConnection){
+                auxConnections.put(auxConnection.getAuxId(), auxConnection);
+                auxConnection.setListener(OFSwitchHandshakeHandler.this);
+
+                // Only handle success case
+                if(auxConnections.size() == this.numAux){
+                    if(log.isDebugEnabled()) {
+                        log.debug("[{}] - all {} required aux connections open. Proceeding",
+                                getDpid(), numAux);
+                    }
+                    gotoNextState();
+                } else {
+                    log.debug("[" + getDpid() + "] - {} / {} required aux connections open. Waiting for more connections. ",
+                            auxConnections.size(), numAux);
+                }
+            }
+
+            @Override
+            void processOFError(OFErrorMsg m) {
+                log.info("Received error on OF Aux handshake - switch does not support OF Aux: {}", m);
+                gotoNextState();
+            }
+
+            void gotoNextState(){
+                // Register any aux connections that have been receieved.
+                for (IOFConnectionBackend conn : auxConnections.values()) {
+                    sw.registerConnection(conn);
+                }
+                setState(new WaitGentableDescStatsReplyState());
+            }
+
+            @Override
+            public void enterState() {
+                this.numAux = switchManager.getNumRequiredConnections();
+                sendOFAuxSetCxnsRequest(this.numAux);
+            }
+
+            @Override
+            void processOFPortStatus(OFPortStatus m) {
+                handlePortStatusMessage(m, false);
+            }
+        }
+
+        /**
+         * We have requested the GenTable mapping (OFBsnGenTableDescStatsRequest)
+         * and are waiting on the reply / replies (note: it is a multipart message).
+         * Once we're received all parts, we create a GenTableMapping object and
+         * set it in the switch.
+         *
+         * If we receive an error messsage corresponding to our request, we conclude
+         * that the switch doesn't support GenTables and leave the empty default
+         * mapping in the switch.
+         *
+         * Next state: WaitSwitchDriverSubHandshakeState() if a driver handshake is required
+         *     WaitAppHandshake else
+         */
+        public class WaitGentableDescStatsReplyState extends OFSwitchHandshakeState {
+
+            private final List<OFBsnGentableDescStatsReply> pendingGenTableDescStatsReplies;
+            private final long pendingRequestXid;
+
+            WaitGentableDescStatsReplyState() {
+                super(false);
+                pendingGenTableDescStatsReplies = new CopyOnWriteArrayList<>();
+                pendingRequestXid = sendHandshakeGenTableDescStatsRequest();
+            }
+
+            @Override
+            void processOFStatsReply(OFStatsReply m) {
+                // Read description, if it has been updated
+                if (!(m instanceof OFBsnGentableDescStatsReply)) {
+                    illegalMessageReceived(m);
+                    return;
+                }
+
+                OFBsnGentableDescStatsReply reply = (OFBsnGentableDescStatsReply) m;
+
+                pendingGenTableDescStatsReplies.add(reply);
+                if(reply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
+                    // more replies to follow, stay in state
+                    return;
+                }
+
+                if(sw == null) {
+                    throw new IllegalArgumentException("Switch instance unknown at time of GenTableDescStatsReply");
+                }
+
+                GenTableMap genTableMap = GenTableMap.of(pendingGenTableDescStatsReplies);
+                if(log.isDebugEnabled())
+                    log.debug("[{}] Gen Tables: {}", sw.getId(), genTableMap);
+                sw.setGenTableMap(genTableMap);
+
+                gotoNextState();
+            }
+
+            public void gotoNextState() {
+                sw.startDriverHandshake();
+                if (sw.isDriverHandshakeComplete())
+                    setState(new WaitAppHandshakeState());
+                else
+                    setState(new WaitSwitchDriverSubHandshakeState());
+            }
+
+            @Override
+            void processOFError(OFErrorMsg m) {
+                if(m.getXid() == pendingRequestXid) {
+                    // let switch continue with an empty set of gentables
+                    log.info("Received error on GenTable handshake - switch does not support gentables: {}", m);
+                    gotoNextState();
+                } else {
+                    illegalMessageReceived(m);
+                }
+            }
+
+            @Override
+            void processOFPortStatus(OFPortStatus m) {
+                handlePortStatusMessage(m, false);
+            }
+        }
+
+        public class WaitSwitchDriverSubHandshakeState extends OFSwitchHandshakeState {
+
+            WaitSwitchDriverSubHandshakeState() {
+                super(false);
+            }
+
+            @Override
+            void processOFMessage(OFMessage m) {
+                // FIXME: other message to handle here?
+                sw.processDriverHandshakeMessage(m);
+                if (sw.isDriverHandshakeComplete()) {
+                    setState(new WaitAppHandshakeState());
+                }
+            }
+
+            @Override
+            void processOFPortStatus(OFPortStatus m) {
+                handlePortStatusMessage(m, false);
+            }
+        }
+
+    public class WaitAppHandshakeState extends OFSwitchHandshakeState {
+
+        private final Iterator<IAppHandshakePluginFactory> pluginIterator;
+        private OFSwitchAppHandshakePlugin plugin;
+
+        WaitAppHandshakeState() {
+            super(false);
+            this.pluginIterator = switchManager.getHandshakePlugins().iterator();
+        }
+
+        @Override
+        void processOFMessage(OFMessage m) {
+            if(m.getType() == OFType.PORT_STATUS){
+                OFPortStatus status = (OFPortStatus) m;
+                handlePortStatusMessage(status, false);
+            }
+            else if(plugin != null){
+                this.plugin.processOFMessage(m);
+            }
+            else{
+                super.processOFMessage(m);
+            }
+        }
+
+        /**
+         * Called by handshake plugins to signify that they have finished their
+         * sub handshake.
+         *
+         * @param result
+         *            the result of the sub handshake
+         */
+        void exitPlugin(PluginResult result) {
+
+            // Proceed
+            if (result.getResultType() == PluginResultType.CONTINUE) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}."
+                            + " Proceeding normally..",
+                            this.plugin.getClass().getSimpleName(), result);
+                }
+
+                enterNextPlugin();
+
+            // Stop
+            } else if (result.getResultType() == PluginResultType.DISCONNECT) {
+                log.error("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}. "
+                        + "Disconnecting switch.",
+                        this.plugin.getClass().getSimpleName(), result);
+                mainConnection.disconnect();
+            } else if (result.getResultType() == PluginResultType.QUARANTINE) {
+                log.warn("Switch " + getSwitchInfoString() + " app handshake plugin {} returned {}. "
+                        + "Putting switch into quarantine state.",
+                        this.plugin.getClass().getSimpleName(),
+                         result);
+                setState(new QuarantineState(result.getReason()));
+            }
+        }
+
+        @Override
+        public void enterState() {
+            enterNextPlugin();
+        }
+
+        /**
+         * Initialize the plugin and begin.
+         *
+         * @param plugin the of switch app handshake plugin
+         */
+        public void enterNextPlugin() {
+            if(this.pluginIterator.hasNext()){
+                this.plugin = pluginIterator.next().createPlugin();
+                this.plugin.init(this, sw, timer);
+                this.plugin.enterPlugin();
+            }
+            // No more plugins left...
+            else{
+                // Non OF 1.3
+                if(featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0){
+                    setState(new WaitInitialRoleState());
+                } else {
+                    setState(new WaitControllerCxnsReplyState());
+                }
+            }
+        }
+
+        @Override
+        void processOFPortStatus(OFPortStatus m) {
+            handlePortStatusMessage(m, false);
+        }
+
+        OFSwitchAppHandshakePlugin getCurrentPlugin() {
+            return plugin;
+        }
+
+    }
+
+    /**
+     * Switch is in a quarantine state. Essentially the handshake is complete.
+     */
+    public class QuarantineState extends OFSwitchHandshakeState {
+
+        private final String quarantineReason;
+
+        QuarantineState(String reason) {
+            super(true);
+            this.quarantineReason = reason;
+        }
+
+        @Override
+        public void enterState() {
+            setSwitchStatus(SwitchStatus.QUARANTINED);
+        }
+
+        @Override
+        void processOFPortStatus(OFPortStatus m) {
+            handlePortStatusMessage(m, false);
+        }
+
+        public String getQuarantineReason() {
+            return this.quarantineReason;
+        }
+    }
+
+    public class WaitControllerCxnsReplyState extends OFSwitchHandshakeState {
+
+        WaitControllerCxnsReplyState() {
+            super(false);
+        }
+
+        @Override
+        void processOFExperimenter(OFExperimenter m) {
+            if(m instanceof OFBsnControllerConnectionsReply) {
+                OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
+                handleControllerConnectionMessage(reply);
+
+                setState(new WaitInitialRoleState());
+            } else {
+                unhandledMessageReceived(m);
+            }
+        }
+
+        @Override
+        void processOFPortStatus(OFPortStatus m) {
+            handlePortStatusMessage(m, false);
+        }
+
+        @Override
+        public void enterState() {
+            // Write out request down
+            OFBsnControllerConnectionsRequest request = factory.buildBsnControllerConnectionsRequest()
+                    .build();
+            mainConnection.write(request);
+
+        }
+
+    }
+
+    /**
+     * We are waiting for the initial role reply message (or error indication)
+     * from the switch. Next State: MASTER or SLAVE
+     */
+        public class WaitInitialRoleState extends OFSwitchHandshakeState {
+
+            WaitInitialRoleState() {
+                super(false);
+            }
+
+            @Override
+            void processOFError(OFErrorMsg m) {
+                // role changer will ignore the error if it isn't for it
+                boolean didHandle = roleChanger.deliverError(m);
+                if (!didHandle) {
+                    logError(m);
+                }
+            }
+
+            @Override
+            void processOFExperimenter(OFExperimenter m) {
+                OFControllerRole role = extractNiciraRoleReply(m);
+                // If role == null it measn the message wasn't really a
+                // Nicira role reply. We ignore this case.
+                if (role != null) {
+                    roleChanger.deliverRoleReply(m.getXid(), role);
+                } else if(m instanceof OFBsnControllerConnectionsReply) {
+                    OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
+                    handleControllerConnectionMessage(reply);
+                } else {
+                    unhandledMessageReceived(m);
+                }
+            }
+
+            @Override
+            void processOFRoleReply(OFRoleReply m) {
+                roleChanger.deliverRoleReply(m.getXid(), m.getRole());
+            }
+
+            @Override
+            void processOFStatsReply(OFStatsReply m) {
+                illegalMessageReceived(m);
+            }
+
+            @Override
+            void processOFPortStatus(OFPortStatus m) {
+                handlePortStatusMessage(m, false);
+            }
+
+            @Override
+            void enterState(){
+                sendRoleRequest(roleManager.getOFControllerRole());
+            }
+        }
+
+        /**
+         * The switch is in MASTER role. We enter this state after a role
+         * reply from the switch is received (or the controller is MASTER
+         * and the switch doesn't support roles). The handshake is complete at
+         * this point. We only leave this state if the switch disconnects or
+         * if we send a role request for SLAVE /and/ receive the role reply for
+         * SLAVE.
+         */
+        public class MasterState extends OFSwitchHandshakeState {
+
+            MasterState() {
+                super(true);
+            }
+
+            @Override
+            void enterState() {
+                setSwitchStatus(SwitchStatus.MASTER);
+            }
+
+            @LogMessageDoc(level="WARN",
+                message="Received permission error from switch {} while" +
+                         "being master. Reasserting master role.",
+                explanation="The switch has denied an operation likely " +
+                         "indicating inconsistent controller roles",
+                recommendation="This situation can occurs transiently during role" +
+                 " changes. If, however, the condition persists or happens" +
+                 " frequently this indicates a role inconsistency. " +
+                 LogMessageDoc.CHECK_CONTROLLER )
+            @Override
+            void processOFError(OFErrorMsg m) {
+                // role changer will ignore the error if it isn't for it
+                boolean didHandle = roleChanger.deliverError(m);
+                if (didHandle)
+                    return;
+                if ((m.getErrType() == OFErrorType.BAD_REQUEST) &&
+                        (((OFBadRequestErrorMsg)m).getCode() == OFBadRequestCode.EPERM)) {
+                    // We are the master controller and the switch returned
+                    // a permission error. This is a likely indicator that
+                    // the switch thinks we are slave. Reassert our
+                    // role
+                    // FIXME: this could be really bad during role transitions
+                    // if two controllers are master (even if its only for
+                    // a brief period). We might need to see if these errors
+                    // persist before we reassert
+                    switchManagerCounters.epermErrorWhileSwitchIsMaster.increment();
+                    log.warn("Received permission error from switch {} while" +
+                             "being master. Reasserting master role.",
+                             getSwitchInfoString());
+                    reassertRole(OFControllerRole.ROLE_MASTER);
+                }
+                else if ((m.getErrType() == OFErrorType.FLOW_MOD_FAILED) &&
+                        (((OFFlowModFailedErrorMsg)m).getCode() == OFFlowModFailedCode.ALL_TABLES_FULL)) {
+                    sw.setTableFull(true);
+                }
+                else {
+                    logError(m);
+                }
+                dispatchMessage(m);
+            }
+
+            @Override
+            void processOFExperimenter(OFExperimenter m) {
+                OFControllerRole role = extractNiciraRoleReply(m);
+                // If role == null it means the message wasn't really a
+                // Nicira role reply. We ignore just dispatch it to the
+                // OFMessage listenersa in this case.
+                if (role != null) {
+                    roleChanger.deliverRoleReply(m.getXid(), role);
+                } else if (m instanceof OFBsnControllerConnectionsReply){
+                    OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
+                    handleControllerConnectionMessage(reply);
+                } else {
+                    dispatchMessage(m);
+                }
+            }
+
+
+            @Override
+            void processOFRoleReply(OFRoleReply m) {
+                roleChanger.deliverRoleReply(m.getXid(), m.getRole());
+            }
+
+            @Override
+            void processOFPortStatus(OFPortStatus m) {
+                handlePortStatusMessage(m, true);
+            }
+
+            @Override
+            void processOFPacketIn(OFPacketIn m) {
+                dispatchMessage(m);
+            }
+
+            @Override
+            void processOFFlowRemoved(OFFlowRemoved m) {
+                dispatchMessage(m);
+            }
+        }
+
+        /**
+         * The switch is in SLAVE role. We enter this state after a role
+         * reply from the switch is received. The handshake is complete at
+         * this point. We only leave this state if the switch disconnects or
+         * if we send a role request for MASTER /and/ receive the role reply for
+         * MASTER.
+         * TODO: CURRENTLY, WE DO NOT DISPATCH ANY MESSAGE IN SLAVE.
+         */
+        public class SlaveState extends OFSwitchHandshakeState {
+
+            SlaveState() {
+                super(true);
+            }
+
+            @Override
+            void enterState() {
+                setSwitchStatus(SwitchStatus.SLAVE);
+            }
+
+            @Override
+            void processOFError(OFErrorMsg m) {
+                // role changer will ignore the error if it isn't for it
+                boolean didHandle = roleChanger.deliverError(m);
+                if (!didHandle) {
+                    logError(m);
+                }
+            }
+
+            @Override
+            void processOFStatsReply(OFStatsReply m) {
+            }
+
+            @Override
+            void processOFPortStatus(OFPortStatus m) {
+                handlePortStatusMessage(m, true);
+            }
+
+            @Override
+            void processOFExperimenter(OFExperimenter m) {
+                OFControllerRole role = extractNiciraRoleReply(m);
+                // If role == null it means the message wasn't really a
+                // Nicira role reply. We ignore it.
+                if (role != null) {
+                    roleChanger.deliverRoleReply(m.getXid(), role);
+                } else if (m instanceof OFBsnControllerConnectionsReply){
+                    OFBsnControllerConnectionsReply reply = (OFBsnControllerConnectionsReply) m;
+                    handleControllerConnectionMessage(reply);
+                } else {
+                    unhandledMessageReceived(m);
+                }
+            }
+
+            @Override
+            void processOFRoleReply(OFRoleReply m) {
+                roleChanger.deliverRoleReply(m.getXid(), m.getRole());
+            }
+
+            @Override
+            @LogMessageDoc(level="WARN",
+                message="Received PacketIn from switch {} while" +
+                         "being slave. Reasserting slave role.",
+                explanation="The switch has receive a PacketIn despite being " +
+                         "in slave role indicating inconsistent controller roles",
+                recommendation="This situation can occurs transiently during role" +
+                         " changes. If, however, the condition persists or happens" +
+                         " frequently this indicates a role inconsistency. " +
+                         LogMessageDoc.CHECK_CONTROLLER )
+            void processOFPacketIn(OFPacketIn m) {
+                // we don't expect packetIn while slave, reassert we are slave
+                switchManagerCounters.packetInWhileSwitchIsSlave.increment();
+                log.warn("Received PacketIn from switch {} while" +
+                         "being slave. Reasserting slave role.", sw);
+                reassertRole(OFControllerRole.ROLE_SLAVE);
+            }
+        };
+
+
+    /**
+     * Create a new unconnected OFChannelHandler.
+     * @param controller
+     * @param broker
+     * @throws SwitchHandshakeHandlerException
+     */
+    OFSwitchHandshakeHandler(@Nonnull IOFConnectionBackend connection,
+                             @Nonnull OFFeaturesReply featuresReply,
+                             @Nonnull IOFSwitchManager switchManager,
+                             @Nonnull RoleManager roleManager,
+                             @Nonnull Timer timer) {
+        Preconditions.checkNotNull(connection, "connection");
+        Preconditions.checkNotNull(featuresReply, "featuresReply");
+        Preconditions.checkNotNull(switchManager, "switchManager");
+        Preconditions.checkNotNull(roleManager, "roleManager");
+        Preconditions.checkNotNull(timer, "timer");
+        Preconditions.checkArgument(connection.getAuxId().equals(OFAuxId.MAIN),
+                "connection must be MAIN connection but is %s", connection);
+
+        this.switchManager = switchManager;
+        this.roleManager = roleManager;
+        this.mainConnection = connection;
+        this.auxConnections = new ConcurrentHashMap<OFAuxId, IOFConnectionBackend>();
+        this.featuresReply = featuresReply;
+        this.timer = timer;
+        this.switchManagerCounters = switchManager.getCounters();
+        this.factory = OFFactories.getFactory(featuresReply.getVersion());
+        this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_NS);
+        setState(new InitState());
+        this.pendingPortStatusMsg = new ArrayList<OFPortStatus>();
+
+        connection.setListener(this);
+    }
+
+    /**
+     * This begins the switch handshake. We start where the OFChannelHandler
+     * left off, right after receiving the OFFeaturesReply.
+     */
+    public void beginHandshake() {
+        Preconditions.checkState(state instanceof InitState, "must be in InitState");
+
+        if (this.featuresReply.getNTables() > 1) {
+            log.debug("Have {} table for switch {}", this.featuresReply.getNTables(),
+                      getSwitchInfoString());
+            // likely supports L2 table extensions. Send set
+            sendHandshakeL2TableSet();
+            // TODO: no L2 SET reply yet, so fire and forget the set
+        }
+
+        if(this.featuresReply.getVersion().compareTo(OFVersion.OF_13) < 0) {
+            setState(new WaitConfigReplyState());
+        } else {
+            // OF 1.3. Ask for Port Descriptions
+            setState(new WaitPortDescStatsReplyState());
+        }
+    }
+
+    public DatapathId getDpid(){
+        return this.featuresReply.getDatapathId();
+    }
+
+    public OFAuxId getOFAuxId(){
+        return this.featuresReply.getAuxiliaryId();
+    }
+
+    /**
+     * Is this a state in which the handshake has completed?
+     * @return true if the handshake is complete
+     */
+    public boolean isHandshakeComplete() {
+        return this.state.isHandshakeComplete();
+    }
+
+    /**
+     * Forwards to RoleChanger. See there.
+     * @param role
+     */
+    void sendRoleRequestIfNotPending(OFControllerRole role) {
+        try {
+            roleChanger.sendRoleRequestIfNotPending(role);
+        } catch (IOException e) {
+             log.error("Disconnecting switch {} due to IO Error: {}",
+                              getSwitchInfoString(), e.getMessage());
+             mainConnection.disconnect();
+        }
+    }
+
+
+    /**
+     * Forwards to RoleChanger. See there.
+     * @param role
+     */
+    void sendRoleRequest(OFControllerRole role) {
+        try {
+            roleChanger.sendRoleRequest(role);
+        } catch (IOException e) {
+             log.error("Disconnecting switch {} due to IO Error: {}",
+                              getSwitchInfoString(), e.getMessage());
+             mainConnection.disconnect();
+        }
+    }
+
+    /**
+     * Dispatches the message to the controller packet pipeline
+     */
+    private void dispatchMessage(OFMessage m) {
+        this.switchManager.handleMessage(this.sw, m, null);
+    }
+
+    /**
+     * Return a string describing this switch based on the already available
+     * information (DPID and/or remote socket)
+     * @return
+     */
+    private String getSwitchInfoString() {
+        if (sw != null)
+            return sw.toString();
+        String channelString;
+        if (mainConnection == null || mainConnection.getRemoteInetAddress() == null) {
+            channelString = "?";
+        } else {
+            channelString = mainConnection.getRemoteInetAddress().toString();
+        }
+        String dpidString;
+        if (featuresReply == null) {
+            dpidString = "?";
+        } else {
+            dpidString = featuresReply.getDatapathId().toString();
+        }
+        return String.format("[%s DPID[%s]]", channelString, dpidString);
+    }
+
+    /**
+     * Update the channels state. Only called from the state machine.
+     * TODO: enforce restricted state transitions
+     * @param state
+     */
+    private void setState(OFSwitchHandshakeState state) {
+        this.state = state;
+        state.logState();
+        state.enterState();
+    }
+
+    private void sendOFAuxSetCxnsRequest(int numAux) {
+        OFBsnSetAuxCxnsRequest request = factory.buildBsnSetAuxCxnsRequest()
+                .setNumAux(numAux)
+                .build();
+        mainConnection.write(request);
+    }
+
+    public void processOFMessage(OFMessage m) {
+        state.processOFMessage(m);
+    }
+
+    /**
+     * Send the configuration requests to tell the switch we want full
+     * packets
+     * @throws IOException
+     */
+    private void sendHandshakeSetConfig() {
+        // Ensure we receive the full packet via PacketIn
+        // FIXME: We don't set the reassembly flags.
+        OFSetConfig configSet = factory.buildSetConfig()
+                .setXid(handshakeTransactionIds--)
+                .setMissSendLen(0xffff)
+                .build();
+
+        // Barrier
+        OFBarrierRequest barrier = factory.buildBarrierRequest()
+                .setXid(handshakeTransactionIds--)
+                .build();
+
+        // Verify (need barrier?)
+        OFGetConfigRequest configReq = factory.buildGetConfigRequest()
+                .setXid(handshakeTransactionIds--)
+                .build();
+        List<OFMessage> msgList = ImmutableList.<OFMessage>of(configSet, barrier, configReq);
+        mainConnection.write(msgList);
+    }
+
+    protected void sendPortDescRequest() {
+        mainConnection.write(factory.portDescStatsRequest(ImmutableSet.<OFStatsRequestFlags>of()));
+    }
+
+    /**
+     * send a description state request
+     */
+    private void sendHandshakeDescriptionStatsRequest() {
+        // Send description stats request to set switch-specific flags
+        OFDescStatsRequest descStatsRequest = factory.buildDescStatsRequest()
+                .setXid(handshakeTransactionIds--)
+                .build();
+        mainConnection.write(descStatsRequest);
+    }
+
+    /** send a BSN GenTable DescStats Request, querying for the tables
+     *  available at the switch.
+     * @return
+     */
+    private long sendHandshakeGenTableDescStatsRequest() {
+        long xid = handshakeTransactionIds--;
+        OFBsnGentableDescStatsRequest descStatsRequest = factory.buildBsnGentableDescStatsRequest()
+                .setXid(xid)
+                .build();
+
+        mainConnection.write(descStatsRequest);
+        return xid;
+    }
+
+    //TODO: Can we nuke this? - jason
+    /**
+     * Send an setL2TableSet message to the switch.
+     */
+    private void sendHandshakeL2TableSet() {
+        // The BsnSetL2Table message is only supported in OF 1.0, so skip if
+        // we're using a later version
+        if (factory.getVersion() != OFVersion.OF_10)
+            return;
+
+        OFBsnSetL2TableRequest m = factory.buildBsnSetL2TableRequest()
+                .setXid(handshakeTransactionIds--)
+                .setL2TableEnable(true)
+                .setL2TablePriority(1000)
+                .build();
+        mainConnection.write(m);
+    }
+
+    OFSwitchHandshakeState getStateForTesting() {
+        return state;
+    }
+
+    void reassertRole(OFControllerRole role){
+        this.roleManager.reassertRole(this, HARole.ofOFRole(role));
+    }
+
+    void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) {
+        roleChanger = new RoleChanger(TimeUnit.MILLISECONDS.toNanos(roleTimeoutMs));
+    }
+
+    /**
+     * Called by the switch manager when new aux connections have connected.
+     * This alerts the state machine of an aux connection.
+     *
+     * @param connection
+     *            the aux connection
+     */
+    public synchronized void auxConnectionOpened(IOFConnectionBackend connection) {
+        if(log.isDebugEnabled())
+            log.debug("[{}] - Switch Handshake - new aux connection {}",
+                    this.getDpid(), connection.getAuxId());
+        this.state.auxConnectionOpened(connection);
+    }
+
+    /**
+     * Gets the main connection
+     *
+     * @return the main connection
+     */
+    public IOFConnectionBackend getMainConnection() {
+        return this.mainConnection;
+    }
+
+    /**
+     * Determines if this handshake handler is responsible for the supplied
+     * connection.
+     *
+     * @param connection
+     *            an OF connection
+     * @return true if the handler has the connection
+     */
+    public boolean hasConnection(IOFConnectionBackend connection) {
+        if (this.mainConnection.equals(connection)
+            || this.auxConnections.get(connection.getAuxId()) == connection) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    void cleanup() {
+        for (IOFConnectionBackend conn : this.auxConnections.values()) {
+            conn.disconnect();
+        }
+
+        this.mainConnection.disconnect();
+    }
+
+    public String getState() {
+        return this.state.getClass().getSimpleName();
+    }
+
+    public String getQuarantineReason() {
+        if(this.state instanceof QuarantineState) {
+            QuarantineState qs = (QuarantineState) this.state;
+            return qs.getQuarantineReason();
+        }
+        return null;
+    }
+
+    /**
+     * Gets the current connections that this switch handshake handler is
+     * responsible for. Used primarily by the REST API.
+     * @return an immutable list of IOFConnections
+     */
+    public ImmutableList<IOFConnection> getConnections() {
+        ImmutableList.Builder<IOFConnection> builder = ImmutableList.builder();
+
+        builder.add(mainConnection);
+        builder.addAll(auxConnections.values());
+
+        return builder.build();
+    }
+
+
+    /** IOFConnectionListener */
+    @Override
+    public void connectionClosed(IOFConnectionBackend connection) {
+        // Disconnect handler's remaining connections
+        cleanup();
+
+        // Only remove the switch handler when the main connection is
+        // closed
+        if (connection == this.mainConnection) {
+            switchManager.handshakeDisconnected(connection.getDatapathId());
+            if(sw != null) {
+                log.debug("[{}] - main connection {} closed - disconnecting switch",
+                          connection);
+
+                setSwitchStatus(SwitchStatus.DISCONNECTED);
+                switchManager.switchDisconnected(sw);
+            }
+        }
+    }
+
+    @Override
+    public void messageReceived(IOFConnectionBackend connection, OFMessage m) {
+        processOFMessage(m);
+    }
+
+    @Override
+    public boolean isSwitchHandshakeComplete(IOFConnectionBackend connection) {
+        return state.isHandshakeComplete();
+    }
+
+    public void setSwitchStatus(SwitchStatus status) {
+        if(sw != null) {
+            SwitchStatus oldStatus = sw.getStatus();
+            if(oldStatus != status) {
+                sw.setStatus(status);
+                switchManager.switchStatusChanged(sw, oldStatus, status);
+            } else {
+                log.warn("[{}] SwitchStatus change to {} requested, switch is already in status",
+                        mainConnection.getDatapathId());
+            }
+        } else {
+            log.warn("[{}] SwitchStatus change to {} requested, but switch is not allocated yet",
+                    mainConnection.getDatapathId());
+        }
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
deleted file mode 100644
index 51dfddc1a..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
-*    Copyright 2012, Big Switch Networks, Inc.
-*    Originally created by David Erickson, Stanford University
-*
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core.internal;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.openflow.protocol.statistics.OFDescriptionStatistics;
-
-import net.floodlightcontroller.core.OFSwitchBase;
-
-/**
- * This is the internal representation of an openflow switch.
- */
-public class OFSwitchImpl extends OFSwitchBase {
-
-    @Override
-    @JsonIgnore
-    public void setSwitchProperties(OFDescriptionStatistics description) {
-        this.description = new OFDescriptionStatistics(description);
-    }
-
-    @Override
-    public OFPortType getPortType(short port_num) {
-        return OFPortType.NORMAL;
-    }
-
-    @Override
-    @JsonIgnore
-    public boolean isFastPort(short port_num) {
-        return false;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
new file mode 100644
index 000000000..dd1cc86b7
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchManager.java
@@ -0,0 +1,756 @@
+package net.floodlightcontroller.core.internal;
+
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.Executors;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.HAListenerTypeMarker;
+import net.floodlightcontroller.core.HARole;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IHAListener;
+import net.floodlightcontroller.core.IOFConnectionBackend;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IOFSwitch.SwitchStatus;
+import net.floodlightcontroller.core.IOFSwitchBackend;
+import net.floodlightcontroller.core.IOFSwitchDriver;
+import net.floodlightcontroller.core.IOFSwitchListener;
+import net.floodlightcontroller.core.LogicalOFMessageCategory;
+import net.floodlightcontroller.core.PortChangeType;
+import net.floodlightcontroller.core.SwitchDescription;
+import net.floodlightcontroller.core.annotations.LogMessageDoc;
+import net.floodlightcontroller.core.annotations.LogMessageDocs;
+import net.floodlightcontroller.core.internal.Controller.IUpdate;
+import net.floodlightcontroller.core.internal.Controller.ModuleLoaderState;
+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.core.rest.SwitchRepresentation;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+import net.floodlightcontroller.debugevent.IDebugEventService;
+import net.floodlightcontroller.debugevent.IDebugEventService.EventType;
+import net.floodlightcontroller.debugevent.IEventCategory;
+import net.floodlightcontroller.debugevent.MockDebugEventService;
+
+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.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFAuxId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * The Switch Manager class contains most of the code involved with dealing
+ * with switches. The Switch manager keeps track of the switches known to the controller,
+ * their status, and any important information about the switch lifecycle. The
+ * Switch Manager also provides the switch service, which allows other modules
+ * to hook in switch listeners and get basic access to switch information.
+ *
+ * @author gregor, capveg, sovietaced
+ *
+ */
+public class OFSwitchManager implements IOFSwitchManager, INewOFConnectionListener, IHAListener, IFloodlightModule, IOFSwitchService {
+    private static final Logger log = LoggerFactory.getLogger(OFSwitchManager.class);
+
+    private volatile OFControllerRole role;
+    private SwitchManagerCounters counters;
+
+    private ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler> switchHandlers;
+    private ConcurrentHashMap<DatapathId, IOFSwitchBackend> switches;
+
+    private ISwitchDriverRegistry driverRegistry;
+
+    private Set<LogicalOFMessageCategory> logicalOFMessageCategories = new CopyOnWriteArraySet<LogicalOFMessageCategory>();
+    private final List<IAppHandshakePluginFactory> handshakePlugins = new CopyOnWriteArrayList<IAppHandshakePluginFactory>();
+    private int numRequiredConnections = -1;
+    // Event IDs for debug events
+    protected IEventCategory<SwitchEvent> evSwitch;
+
+    // ISwitchService
+    protected Set<IOFSwitchListener> switchListeners;
+
+    // Module Dependencies
+    IFloodlightProviderService floodlightProvider;
+    IDebugEventService debugEventService;
+    IDebugCounterService debugCounterService;
+
+    /** IHAListener Implementation **/
+    @Override
+    public void transitionToActive() {
+        this.role = HARole.ACTIVE.getOFRole();
+    }
+
+    @Override
+    public void transitionToStandby() {
+       this.role = HARole.STANDBY.getOFRole();
+    }
+
+    /** IOFSwitchManager Implementation **/
+
+    @Override public SwitchManagerCounters getCounters() {
+        return this.counters;
+    }
+
+    private void addUpdateToQueue(IUpdate iUpdate) {
+        floodlightProvider.addUpdateToQueue(iUpdate);
+    }
+
+    @Override
+    public synchronized void switchAdded(IOFSwitchBackend sw) {
+        DatapathId dpid = sw.getId();
+        IOFSwitchBackend oldSw = this.switches.put(dpid, sw);
+        // Update event history
+        evSwitch.newEventWithFlush(new SwitchEvent(dpid, "connected"));
+
+        if (oldSw == sw)  {
+            // Note == for object equality, not .equals for value
+            counters.errorActivatedSwitchNotPresent
+                         .increment();
+            log.error("Switch {} added twice?", sw);
+            return;
+        } else if (oldSw != null) {
+            // This happens either when we have switches with duplicate
+            // DPIDs or when a switch reconnects before we saw the
+            // disconnect
+            counters.switchWithSameDpidActivated
+                        .increment();
+            log.warn("New switch added {} for already-added switch {}", sw, oldSw);
+            // We need to disconnect and remove the old switch
+            // TODO: we notify switch listeners that the switch has been
+            // removed and then we notify them that the new one has been
+            // added. One could argue that a switchChanged notification
+            // might be more appropriate in this case....
+            oldSw.cancelAllPendingRequests();
+            addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED));
+            oldSw.disconnect();
+        }
+
+    }
+
+    @LogMessageDocs({
+    @LogMessageDoc(level="ERROR",
+            message="Switch {switch} activated but was already active",
+            explanation="A switch that was already activated was " +
+                        "activated again. This should not happen.",
+            recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG
+            ),
+    @LogMessageDoc(level="WARN",
+            message="New switch added {switch} for already-added switch {switch}",
+            explanation="A switch with the same DPID as another switch " +
+                    "connected to the controller.  This can be caused by " +
+                    "multiple switches configured with the same DPID, or " +
+                    "by a switch reconnected very quickly after " +
+                    "disconnecting.",
+            recommendation="If this happens repeatedly, it is likely there " +
+                    "are switches with duplicate DPIDs on the network.  " +
+                    "Reconfigure the appropriate switches.  If it happens " +
+                    "very rarely, then it is likely this is a transient " +
+                    "network problem that can be ignored."
+            )
+    })
+    @Override
+    public synchronized void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus, SwitchStatus newStatus) {
+        DatapathId dpid = sw.getId();
+        IOFSwitchBackend presentSw = this.switches.get(dpid);
+
+        if (presentSw != sw)  {
+            // Note == for object equality, not .equals for value
+            counters.errorActivatedSwitchNotPresent
+                         .increment();
+            log.warn("Switch {} status change but not present in sync manager", sw);
+            return;
+        }
+        evSwitch.newEventWithFlush(new SwitchEvent(dpid,
+                                                   String.format("%s -> %s",
+                                                                 oldStatus,
+                                                                 newStatus)));
+
+        if(newStatus == SwitchStatus.MASTER  && role != OFControllerRole.ROLE_MASTER) {
+            counters.invalidSwitchActivatedWhileSlave.increment();
+            log.error("Switch {} activated but controller not MASTER", sw);
+            sw.disconnect();
+            return; // only react to switch connections when master
+        }
+
+        if(!oldStatus.isVisible() && newStatus.isVisible()) {
+            // the switch has just become visible. Send 'add' notification to our
+            // listeners
+            addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.ADDED));
+        } else if((oldStatus.isVisible() && !newStatus.isVisible())) {
+            addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED));
+        }
+
+        // note: no else if - both may be true
+        if(oldStatus != SwitchStatus.MASTER && newStatus == SwitchStatus.MASTER ) {
+            counters.switchActivated.increment();
+            addUpdateToQueue(new SwitchUpdate(dpid,
+                    SwitchUpdateType.ACTIVATED));
+        } else if(oldStatus == SwitchStatus.MASTER && newStatus != SwitchStatus.MASTER ) {
+            counters.switchDeactivated.increment();
+            addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.DEACTIVATED));
+        }
+    }
+
+    @Override
+    public synchronized void switchDisconnected(IOFSwitchBackend sw) {
+        DatapathId dpid = sw.getId();
+        IOFSwitchBackend presentSw = this.switches.get(dpid);
+
+        if (presentSw != sw)  {
+            // Note == for object equality, not .equals for value
+            counters.errorActivatedSwitchNotPresent
+                         .increment();
+            log.warn("Switch {} disconnect but not present in sync manager", sw);
+            return;
+        }
+
+        counters.switchDisconnected.increment();
+        this.switches.remove(dpid);
+    }
+
+    @Override public void handshakeDisconnected(DatapathId dpid) {
+        this.switchHandlers.remove(dpid);
+    }
+
+    public Iterable<IOFSwitch> getActiveSwitches() {
+        ImmutableList.Builder<IOFSwitch> builder = ImmutableList.builder();
+        for(IOFSwitch sw: switches.values()) {
+            if(sw.getStatus().isControllable())
+                builder.add(sw);
+        }
+        return builder.build();
+    }
+
+    public Map<DatapathId, IOFSwitch> getAllSwitchMap(boolean showInvisible) {
+        if(showInvisible) {
+            return ImmutableMap.<DatapathId, IOFSwitch>copyOf(switches);
+        } else {
+            ImmutableMap.Builder<DatapathId, IOFSwitch> builder = ImmutableMap.builder();
+            for(IOFSwitch sw: switches.values()) {
+                if(sw.getStatus().isVisible())
+                    builder.put(sw.getId(), sw);
+            }
+            return builder.build();
+        }
+    }
+
+    @Override
+    public Map<DatapathId, IOFSwitch> getAllSwitchMap() {
+        return getAllSwitchMap(true);
+    }
+
+    @Override
+    public Set<DatapathId> getAllSwitchDpids() {
+        return getAllSwitchMap().keySet();
+    }
+
+    public Set<DatapathId> getAllSwitchDpids(boolean showInvisible) {
+        return getAllSwitchMap(showInvisible).keySet();
+    }
+
+    @Override
+    public IOFSwitch getSwitch(DatapathId dpid) {
+        return this.switches.get(dpid);
+    }
+
+    @Override
+    public IOFSwitch getActiveSwitch(DatapathId dpid) {
+        IOFSwitchBackend sw = this.switches.get(dpid);
+        if(sw != null && sw.getStatus().isVisible())
+            return sw;
+        else
+            return null;
+    }
+
+    enum SwitchUpdateType {
+        ADDED,
+        REMOVED,
+        ACTIVATED,
+        DEACTIVATED,
+        PORTCHANGED,
+        OTHERCHANGE
+    }
+
+    /**
+     * Update message indicating a switch was added or removed
+     */
+    class SwitchUpdate implements IUpdate {
+        private final DatapathId swId;
+        private final SwitchUpdateType switchUpdateType;
+        private final OFPortDesc port;
+        private final PortChangeType changeType;
+
+        public SwitchUpdate(DatapathId swId, SwitchUpdateType switchUpdateType) {
+            this(swId, switchUpdateType, null, null);
+        }
+
+        public SwitchUpdate(DatapathId swId,
+                            SwitchUpdateType switchUpdateType,
+                            OFPortDesc port,
+                            PortChangeType changeType) {
+            if (switchUpdateType == SwitchUpdateType.PORTCHANGED) {
+                if (port == null) {
+                    throw new NullPointerException("Port must not be null " +
+                            "for PORTCHANGED updates");
+                }
+                if (changeType == null) {
+                    throw new NullPointerException("ChangeType must not be " +
+                            "null for PORTCHANGED updates");
+                }
+            } else {
+                if (port != null || changeType != null) {
+                    throw new IllegalArgumentException("port and changeType " +
+                            "must be null for " + switchUpdateType +
+                            " updates");
+                }
+            }
+            this.swId = swId;
+            this.switchUpdateType = switchUpdateType;
+            this.port = port;
+            this.changeType = changeType;
+        }
+
+        @Override
+        public void dispatch() {
+            if (log.isTraceEnabled()) {
+                log.trace("Dispatching switch update {} {}", swId, switchUpdateType);
+            }
+            if (switchListeners != null) {
+                for (IOFSwitchListener listener : switchListeners) {
+                    switch(switchUpdateType) {
+                        case ADDED:
+                            // don't count here. We have more specific
+                            // counters before the update is created
+                            listener.switchAdded(swId);
+                            break;
+                        case REMOVED:
+                            // don't count here. We have more specific
+                            // counters before the update is created
+                            listener.switchRemoved(swId);
+                            break;
+                        case PORTCHANGED:
+                            counters.switchPortChanged
+                                    .increment();
+                            listener.switchPortChanged(swId, port, changeType);
+                            break;
+                        case ACTIVATED:
+                            // don't count here. We have more specific
+                            // counters before the update is created
+                            listener.switchActivated(swId);
+                            break;
+                        case DEACTIVATED:
+                            // ignore
+                            break;
+                        case OTHERCHANGE:
+                            counters.switchOtherChange
+                                    .increment();
+                            listener.switchChanged(swId);
+                            break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Handles a new OF Connection
+     * @param IOFConnectionBackend connection an opened OF Connection
+     * @param OFFeaturesReply featuresReply the features reply received for the opened connection.
+     * It is needed for the rest of the switch handshake.
+     */
+    @Override
+    public void connectionOpened(IOFConnectionBackend connection,
+                                 OFFeaturesReply featuresReply) {
+        DatapathId dpid = connection.getDatapathId();
+        OFAuxId auxId = connection.getAuxId();
+
+        log.debug("{} opened", connection);
+
+        if(auxId.equals(OFAuxId.MAIN)) {
+
+            // Create a new switch handshake handler
+            OFSwitchHandshakeHandler handler =
+                    new OFSwitchHandshakeHandler(connection, featuresReply, this,
+                            floodlightProvider.getRoleManager(), floodlightProvider.getTimer());
+
+            OFSwitchHandshakeHandler oldHandler = switchHandlers.put(dpid, handler);
+
+            // Disconnect all the handler's connections
+            if(oldHandler != null){
+                log.debug("{} is a new main connection, killing old handler connections",
+                          connection);
+                oldHandler.cleanup();
+            }
+
+            handler.beginHandshake();
+
+        } else {
+            OFSwitchHandshakeHandler handler = switchHandlers.get(dpid);
+
+            if(handler != null) {
+                handler.auxConnectionOpened(connection);
+            }
+            // Connections have arrived before the switchhandler is ready
+            else {
+                log.warn("{} arrived before main connection, closing connection", connection);
+                connection.disconnect();
+            }
+        }
+    }
+
+    @Override
+    public void addSwitchEvent(DatapathId dpid, String reason, boolean flushNow) {
+        if (flushNow)
+            evSwitch.newEventWithFlush(new SwitchEvent(dpid, reason));
+        else
+            evSwitch.newEventNoFlush(new SwitchEvent(dpid, reason));
+    }
+
+    @Override
+    public synchronized void notifyPortChanged(IOFSwitchBackend sw,
+                           OFPortDesc port,
+                           PortChangeType changeType) {
+        Preconditions.checkNotNull(sw, "switch must not be null");
+        Preconditions.checkNotNull(port, "port must not be null");
+        Preconditions.checkNotNull(changeType, "changeType must not be null");
+
+        if (role != OFControllerRole.ROLE_MASTER) {
+            counters.invalidPortsChanged.increment();
+            return;
+        }
+        if (!this.switches.containsKey(sw.getId())) {
+            counters.invalidPortsChanged.increment();
+            return;
+        }
+
+        if(sw.getStatus().isVisible()) {
+            // no need to count here. SwitchUpdate.dispatch will count
+            // the portchanged
+            SwitchUpdate update = new SwitchUpdate(sw.getId(),
+                    SwitchUpdateType.PORTCHANGED,
+                    port, changeType);
+            addUpdateToQueue(update);
+        }
+    }
+
+    @Override
+    public IOFSwitchBackend  getOFSwitchInstance(IOFConnectionBackend connection,
+                                SwitchDescription description,
+                                OFFactory factory, DatapathId datapathId) {
+        return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId);
+    }
+
+    @Override
+    public void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) {
+        floodlightProvider.handleMessage(sw, m, bContext);
+    }
+
+    @Override
+    public void addOFSwitchDriver(String manufacturerDescriptionPrefix,
+                                  IOFSwitchDriver driver) {
+        this.driverRegistry.addSwitchDriver(manufacturerDescriptionPrefix, driver);
+    }
+
+    @Override
+    public ImmutableList<OFSwitchHandshakeHandler> getSwitchHandshakeHandlers() {
+        return ImmutableList.copyOf(this.switchHandlers.values());
+    }
+
+    @Override
+    public int getNumRequiredConnections() {
+        Preconditions.checkState(numRequiredConnections >= 0, "numRequiredConnections not calculated");
+        return numRequiredConnections;
+    }
+
+    public Set<LogicalOFMessageCategory> getLogicalOFMessageCategories() {
+        return logicalOFMessageCategories;
+    }
+
+    private int calcNumRequiredConnections() {
+        if(!this.logicalOFMessageCategories.isEmpty()){
+            // We use tree set here to maintain ordering
+            TreeSet<OFAuxId> auxConnections = new TreeSet<OFAuxId>();
+
+            for(LogicalOFMessageCategory category : this.logicalOFMessageCategories){
+                auxConnections.add(category.getAuxId());
+            }
+
+            OFAuxId first = auxConnections.first();
+            OFAuxId last = auxConnections.last();
+
+            // Check for contiguous set (1....size())
+            if(first.equals(OFAuxId.MAIN)) {
+                if(last.getValue() != auxConnections.size() - 1){
+                    throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (0,1,2,3,4,5)");
+                }
+                return auxConnections.size() - 1;
+            } else if(first.equals(OFAuxId.of(1))) {
+                if(last.getValue() != auxConnections.size()){
+                    throw new IllegalStateException("Logical OF message categories must maintain contiguous OF Aux Ids! i.e. (1,2,3,4,5)");
+                }
+                return auxConnections.size();
+            } else {
+                throw new IllegalStateException("Logical OF message categories must start at 0 (MAIN) or 1");
+            }
+        } else {
+            return 0;
+    }
+    }
+
+    /** ISwitchService Implementation **/
+    @Override
+    public void addOFSwitchListener(IOFSwitchListener listener) {
+        this.switchListeners.add(listener);
+    }
+
+    @Override
+    public void removeOFSwitchListener(IOFSwitchListener listener) {
+        this.switchListeners.remove(listener);
+    }
+
+    @Override
+    public void registerLogicalOFMessageCategory(LogicalOFMessageCategory category) {
+        logicalOFMessageCategories.add(category);
+    }
+
+    @Override
+    public boolean isCategoryRegistered(LogicalOFMessageCategory category) {
+        return logicalOFMessageCategories.contains(category);
+    }
+
+    @Override
+    public SwitchRepresentation getSwitchRepresentation(DatapathId dpid) {
+        IOFSwitch sw = this.switches.get(dpid);
+        OFSwitchHandshakeHandler handler = this.switchHandlers.get(dpid);
+
+        if(sw != null && handler != null) {
+            return new SwitchRepresentation(sw, handler);
+        }
+        return null;
+    }
+
+    @Override
+    public List<SwitchRepresentation> getSwitchRepresentations() {
+
+      List<SwitchRepresentation> representations = new ArrayList<SwitchRepresentation>();
+
+      for(DatapathId dpid : this.switches.keySet()) {
+          SwitchRepresentation representation = getSwitchRepresentation(dpid);
+          if(representation != null) {
+              representations.add(representation);
+          }
+      }
+      return representations;
+    }
+
+    @Override
+    public void registerHandshakePlugin(IAppHandshakePluginFactory factory) {
+        Preconditions.checkState(floodlightProvider.getModuleLoaderState() == ModuleLoaderState.INIT,
+                "handshakeplugins can only be registered when the module loader is in state INIT!");
+        handshakePlugins.add(factory);
+    }
+
+    @Override
+    public List<IAppHandshakePluginFactory> getHandshakePlugins() {
+        return handshakePlugins;
+    }
+
+    /* IFloodlightModule Implementation */
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleServices() {
+        Collection<Class<? extends IFloodlightService>> l =
+                new ArrayList<Class<? extends IFloodlightService>>();
+            l.add(IOFSwitchService.class);
+            return l;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService>
+            getServiceImpls() {
+        Map<Class<? extends IFloodlightService>, IFloodlightService> m =
+                new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+            m.put(IOFSwitchService.class, this);
+            return m;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleDependencies() {
+        Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
+
+        l.add(IFloodlightProviderService.class);
+        l.add(IDebugEventService.class);
+        l.add(IDebugCounterService.class);
+
+        return l;
+    }
+
+    @Override
+    public void init(FloodlightModuleContext context) throws FloodlightModuleException {
+        // Module dependencies
+        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+        debugEventService = context.getServiceImpl(IDebugEventService.class);
+        debugCounterService = context.getServiceImpl(IDebugCounterService.class);
+
+        // Module variables
+        switchHandlers = new ConcurrentHashMap<DatapathId, OFSwitchHandshakeHandler>();
+        switches = new ConcurrentHashMap<DatapathId, IOFSwitchBackend>();
+        floodlightProvider.getTimer();
+        counters = new SwitchManagerCounters(debugCounterService);
+        driverRegistry = new NaiveSwitchDriverRegistry(this);
+
+        this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>();
+
+        this.counters = new SwitchManagerCounters(debugCounterService);
+
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {
+        startUpBase(context);
+        bootstrapNetty();
+    }
+
+    /**
+     * Startup method that includes everything besides the netty boostrap.
+     * This has been isolated for testing.
+     * @param context floodlight module context
+     * @throws FloodlightModuleException
+     */
+    public void startUpBase(FloodlightModuleContext context) throws FloodlightModuleException {
+        // Initial Role
+        role = floodlightProvider.getRole().getOFRole();
+
+        // IRoleListener
+        floodlightProvider.addHAListener(this);
+
+        loadLogicalCategories();
+
+        registerDebugEvents();
+    }
+
+    /**
+     * Bootstraps netty, the server that handles all openflow connections
+     */
+    public void bootstrapNetty() {
+        try {
+            final ServerBootstrap bootstrap = createServerBootStrap();
+
+             bootstrap.setOption("reuseAddr", true);
+             bootstrap.setOption("child.keepAlive", true);
+             bootstrap.setOption("child.tcpNoDelay", true);
+             bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
+
+             ChannelPipelineFactory pfact =
+                     new OpenflowPipelineFactory(this, floodlightProvider.getTimer(), this, debugCounterService);
+             bootstrap.setPipelineFactory(pfact);
+             InetSocketAddress sa = new InetSocketAddress(floodlightProvider.getOFPort());
+             final ChannelGroup cg = new DefaultChannelGroup();
+             cg.add(bootstrap.bind(sa));
+
+             log.info("Listening for switch connections on {}", sa);
+         } catch (Exception e) {
+             throw new RuntimeException(e);
+         }
+    }
+
+    /**
+     * Helper that bootstrapNetty.
+     * @return
+     */
+    private ServerBootstrap createServerBootStrap() {
+        if (floodlightProvider.getWorkerThreads() == 0) {
+            return new ServerBootstrap(
+                    new NioServerSocketChannelFactory(
+                            Executors.newCachedThreadPool(),
+                            Executors.newCachedThreadPool()));
+        } else {
+            return new ServerBootstrap(
+                    new NioServerSocketChannelFactory(
+                            Executors.newCachedThreadPool(),
+                            Executors.newCachedThreadPool(), floodlightProvider.getWorkerThreads()));
+        }
+    }
+
+    /**
+     * Performs startup related actions for logical OF message categories.
+     * Setting the categories list to immutable ensures that unsupported operation
+     * exceptions will be activated if modifications are attempted.
+     */
+    public void loadLogicalCategories() {
+        logicalOFMessageCategories = ImmutableSet.copyOf(logicalOFMessageCategories);
+        numRequiredConnections = calcNumRequiredConnections();
+    }
+
+    /**
+     * Registers an event handler with the debug event service
+     * for switch events.
+     * @throws FloodlightModuleException
+     */
+    private void registerDebugEvents() throws FloodlightModuleException {
+        if (debugEventService == null) {
+            debugEventService = new MockDebugEventService();
+        }
+        evSwitch = debugEventService.buildEvent(SwitchEvent.class)
+                .setModuleName(this.counters.getPrefix())
+                .setEventName("switch-event")
+                .setEventDescription("Switch connected, disconnected or port changed")
+                .setEventType(EventType.ALWAYS_LOG)
+                .setBufferCapacity(100)
+                .register();
+    }
+
+    @Override
+    public String getName() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean isCallbackOrderingPrereq(HAListenerTypeMarker type,
+                                            String name) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isCallbackOrderingPostreq(HAListenerTypeMarker type,
+                                             String name) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+	@Override
+	public void controllerNodeIPsChanged(
+			Map<String, String> curControllerNodeIPs,
+			Map<String, String> addedControllerNodeIPs,
+			Map<String, String> removedControllerNodeIPs) {
+		// TODO Auto-generated method stub
+		
+	}
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java b/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java
deleted file mode 100644
index 82a3c67d6..000000000
--- a/src/main/java/net/floodlightcontroller/core/internal/OpenflowPipelineFactory.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    Licensed under the Apache License, Version 2.0 (the "License"); you may
-*    not use this file except in compliance with the License. You may obtain
-*    a copy of the License at
-*
-*         http://www.apache.org/licenses/LICENSE-2.0
-*
-*    Unless required by applicable law or agreed to in writing, software
-*    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-*    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-*    License for the specific language governing permissions and limitations
-*    under the License.
-**/
-
-package net.floodlightcontroller.core.internal;
-
-import java.util.concurrent.ThreadPoolExecutor;
-
-import org.jboss.netty.channel.ChannelPipeline;
-import org.jboss.netty.channel.ChannelPipelineFactory;
-import org.jboss.netty.channel.Channels;
-import org.jboss.netty.handler.execution.ExecutionHandler;
-import org.jboss.netty.handler.timeout.IdleStateHandler;
-import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
-import org.jboss.netty.util.ExternalResourceReleasable;
-import org.jboss.netty.util.HashedWheelTimer;
-import org.jboss.netty.util.Timer;
-
-/**
- * Creates a ChannelPipeline for a server-side openflow channel
- * @author readams
- */
-public class OpenflowPipelineFactory 
-    implements ChannelPipelineFactory, ExternalResourceReleasable {
-
-    protected Controller controller;
-    protected ThreadPoolExecutor pipelineExecutor;
-    protected Timer timer;
-    protected IdleStateHandler idleHandler;
-    protected ReadTimeoutHandler readTimeoutHandler;
-    
-    public OpenflowPipelineFactory(Controller controller,
-                                   ThreadPoolExecutor pipelineExecutor) {
-        super();
-        this.controller = controller;
-        this.pipelineExecutor = pipelineExecutor;
-        this.timer = new HashedWheelTimer();
-        this.idleHandler = new IdleStateHandler(timer, 20, 25, 0);
-        this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30);
-    }
- 
-    @Override
-    public ChannelPipeline getPipeline() throws Exception {
-        OFChannelHandler handler = new OFChannelHandler(controller);
-        
-        ChannelPipeline pipeline = Channels.pipeline();
-        pipeline.addLast("ofmessagedecoder", new OFMessageDecoder());
-        pipeline.addLast("ofmessageencoder", new OFMessageEncoder());
-        pipeline.addLast("idle", idleHandler);
-        pipeline.addLast("timeout", readTimeoutHandler);
-        pipeline.addLast("handshaketimeout",
-                         new HandshakeTimeoutHandler(handler, timer, 15));
-        if (pipelineExecutor != null)
-            pipeline.addLast("pipelineExecutor",
-                             new ExecutionHandler(pipelineExecutor));
-        pipeline.addLast("handler", handler);
-        return pipeline;
-    }
-
-    @Override
-    public void releaseExternalResources() {
-        timer.stop();        
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/PluginResult.java b/src/main/java/net/floodlightcontroller/core/internal/PluginResult.java
new file mode 100644
index 000000000..e11a527de
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/PluginResult.java
@@ -0,0 +1,40 @@
+package net.floodlightcontroller.core.internal;
+
+import javax.annotation.Nonnull;
+
+import net.floodlightcontroller.core.internal.OFSwitchAppHandshakePlugin.PluginResultType;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Class that represents the result of an app handshake plugin.
+ *
+ */
+public class PluginResult {
+
+    private final PluginResultType result;
+    private final String reason;
+
+    public PluginResult(@Nonnull PluginResultType result) {
+        this.result = result;
+        this.reason = null;
+    }
+
+    public PluginResult(@Nonnull PluginResultType result, String reason) {
+        Preconditions.checkNotNull(result, "result must not be null");
+
+        if(result != PluginResultType.QUARANTINE && reason != null)
+            throw new IllegalStateException("Reason can only be set for Quarantine PluginResult");
+
+        this.result = result;
+        this.reason = reason;
+    }
+
+    public PluginResultType getResultType() {
+        return this.result;
+    }
+
+    public String getReason() {
+        return this.reason;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/internal/RoleManager.java b/src/main/java/net/floodlightcontroller/core/internal/RoleManager.java
new file mode 100644
index 000000000..f37da6707
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/RoleManager.java
@@ -0,0 +1,258 @@
+package net.floodlightcontroller.core.internal;
+
+import java.util.Date;
+import java.util.Map.Entry;
+
+import javax.annotation.Nonnull;
+
+import net.floodlightcontroller.core.HARole;
+import net.floodlightcontroller.core.internal.Controller;
+import net.floodlightcontroller.core.internal.RoleManagerCounters;
+import net.floodlightcontroller.core.IHAListener;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IOFSwitchBackend;
+import net.floodlightcontroller.core.internal.IOFSwitchService;
+import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler;
+import net.floodlightcontroller.core.internal.Controller.IUpdate;
+
+import net.floodlightcontroller.core.internal.RoleManager;
+import net.floodlightcontroller.core.internal.RoleManager.SwitchRoleUpdate;
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import net.floodlightcontroller.core.RoleInfo;
+
+/**
+ * A utility class to manage the <i>controller roles</i>.
+ *
+ * A utility class to manage the <i>controller roles</i>  as opposed
+ * to the switch roles. The class manages the controllers current role,
+ * handles role change requests, and maintains the list of connected
+ * switch(-channel) so it can notify the switches of role changes.
+ *
+ * We need to ensure that every connected switch is always send the
+ * correct role. Therefore, switch add, sending of the intial role, and
+ * changing role need to use mutexes to ensure this. This has the ugly
+ * side-effect of requiring calls between controller and OFChannelHandler
+ *
+ * This class is fully thread safe. Its method can safely be called from
+ * any thread.
+ *
+ * @author gregor
+ *
+ */
+public class RoleManager {
+    private volatile RoleInfo currentRoleInfo;
+    private final Controller controller;
+    private final RoleManagerCounters counters;
+    private volatile boolean notifiedLeader;
+
+    private static final Logger log =
+            LoggerFactory.getLogger(RoleManager.class);
+
+    /**
+     * @param role initial role
+     * @param roleChangeDescription initial value of the change description
+     * @throws NullPointerException if role or roleChangeDescription is null
+     */
+    public RoleManager(@Nonnull Controller controller,
+            @Nonnull HARole role,
+            @Nonnull String roleChangeDescription) {
+        Preconditions.checkNotNull(controller, "controller must not be null");
+        Preconditions.checkNotNull(role, "role must not be null");
+        Preconditions.checkNotNull(roleChangeDescription, "roleChangeDescription must not be null");
+
+        this.currentRoleInfo = new RoleInfo(role,
+                                       roleChangeDescription,
+                                       new Date());
+        this.controller = controller;
+        this.counters = new RoleManagerCounters(controller.getDebugCounter());
+    }
+
+    /**
+     * Re-assert a role for the given channel handler.
+     *
+     * The caller specifies the role that should be reasserted. We only
+     * reassert the role if the controller's current role matches the
+     * reasserted role and there is no role request for the reasserted role
+     * pending.
+     * @param ofSwitchHandshakeHandler The OFChannelHandler on which we should reassert.
+     * @param role The role to reassert
+     */
+    public synchronized void reassertRole(OFSwitchHandshakeHandler ofSwitchHandshakeHandler, HARole role) {
+        // check if the requested reassertion actually makes sense
+        if (this.getRole() != role)
+            return;
+        ofSwitchHandshakeHandler.sendRoleRequestIfNotPending(this.getRole().getOFRole());
+    }
+
+    /**
+     * Set the controller's new role and notify switches.
+     *
+     * This method updates the controllers current role and notifies all
+     * connected switches of the new role is different from the current
+     * role. We dampen calls to this method. See class description for
+     * details.
+     *
+     * @param role The new role.
+     * @param roleChangeDescription A textual description of why the role
+     * was changed. For information purposes only.
+     * @throws NullPointerException if role or roleChangeDescription is null
+     */
+    public synchronized void setRole(@Nonnull HARole role, @Nonnull String roleChangeDescription) {
+        Preconditions.checkNotNull(role, "role must not be null");
+        Preconditions.checkNotNull(roleChangeDescription, "roleChangeDescription must not be null");
+
+        if (role == getRole()) {
+            counters.setSameRole.increment();
+            log.debug("Received role request for {} but controller is "
+                    + "already {}. Ignoring it.", role, this.getRole());
+            return;
+        }
+
+        if (this.getRole() == HARole.STANDBY && role == HARole.ACTIVE) {
+            // At this point we are guaranteed that we will execute the code
+            // below exactly once during the lifetime of this process! And
+            // it will be a to MASTER transition
+            counters.setRoleMaster.increment();
+        }
+
+        log.info("Received role request for {} (reason: {})."
+                + " Initiating transition", role, roleChangeDescription);
+
+        currentRoleInfo =
+                new RoleInfo(role, roleChangeDescription, new Date());
+
+        // NOTE: HARoleUpdate will terminate floodlight on transition to STANDBY
+        controller.addUpdateToQueue(new HARoleUpdate(role));
+        controller.addUpdateToQueue(new SwitchRoleUpdate(role));
+
+    }
+
+    @SuppressFBWarnings(value="UG_SYNC_SET_UNSYNC_GET",
+                        justification = "setter is synchronized for mutual exclusion, "
+                                + "currentRoleInfo is volatile, so no sync on getter needed")
+    public synchronized HARole getRole() {
+        return currentRoleInfo.getRole();
+    }
+
+    public synchronized OFControllerRole getOFControllerRole() {
+        return getRole().getOFRole();
+    }
+
+    /**
+     * Return the RoleInfo object describing the current role.
+     *
+     * Return the RoleInfo object describing the current role. The
+     * RoleInfo object is used by REST API users.
+     * @return the current RoleInfo object
+     */
+    public RoleInfo getRoleInfo() {
+        return currentRoleInfo;
+    }
+
+    private void attemptActiveTransition() {
+         if(!switchesHaveAnotherMaster()){
+             // No valid cluster controller connections found, become ACTIVE!
+             setRole(HARole.ACTIVE, "Leader election assigned ACTIVE role");
+             notifiedLeader = false;
+         }
+     }
+
+    /**
+     * Iterates over all the switches and checks to see if they have controller
+     * connections that points towards another master controller.
+     * @return
+     */
+    private boolean switchesHaveAnotherMaster() {
+        IOFSwitchService switchService = controller.getSwitchService();
+
+        for(Entry<DatapathId, IOFSwitch> switchMap : switchService.getAllSwitchMap().entrySet()){
+            IOFSwitchBackend sw = (IOFSwitchBackend) switchMap.getValue();
+            if(sw.hasAnotherMaster()){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void notifyControllerConnectionUpdate() {
+        if(notifiedLeader && currentRoleInfo.getRole() != HARole.ACTIVE) {
+            attemptActiveTransition();
+        }
+    }
+
+    /**
+     * Update message indicating controller's role has changed.
+     * RoleManager, which enqueues these updates guarantees that we will
+     * only have a single transition from SLAVE to MASTER.
+     *
+     * When the role update from master to slave is complete, the HARoleUpdate
+     * will terminate floodlight.
+     */
+    private class HARoleUpdate implements IUpdate {
+        private final HARole newRole;
+        public HARoleUpdate(HARole newRole) {
+            this.newRole = newRole;
+        }
+
+        @Override
+        public void dispatch() {
+            if (log.isDebugEnabled()) {
+                log.debug("Dispatching HA Role update newRole = {}",
+                          newRole);
+            }
+            for (IHAListener listener : controller.haListeners.getOrderedListeners()) {
+                if (log.isTraceEnabled()) {
+                    log.trace("Calling HAListener {} with transitionTo{}",
+                              listener.getName(), newRole);
+                }
+                switch(newRole) {
+                    case ACTIVE:
+                        listener.transitionToActive();
+                        break;
+                    case STANDBY:
+                        listener.transitionToStandby();
+                        break;
+                }
+           }
+
+           controller.setNotifiedRole(newRole);
+
+           if(newRole == HARole.STANDBY) {
+               String reason = String.format("Received role request to "
+                       + "transition from ACTIVE to STANDBY (reason: %s)",
+                       getRoleInfo().getRoleChangeDescription());
+               //TODO @Ryan shutdownService.terminate(reason, 0);
+           }
+        }
+    }
+
+    public class SwitchRoleUpdate implements IUpdate {
+        private final HARole role;
+
+        public SwitchRoleUpdate(HARole role) {
+            this.role = role;
+        }
+
+        @Override
+        public void dispatch() {
+            if (log.isDebugEnabled()) {
+                log.debug("Dispatching switch role update newRole = {}, switch role = {}",
+                          this.role, this.role.getOFRole());
+            }
+
+            for (OFSwitchHandshakeHandler h: controller.getSwitchService().getSwitchHandshakeHandlers())
+                h.sendRoleRequest(this.role.getOFRole());
+        }
+    }
+
+    public RoleManagerCounters getCounters() {
+        return this.counters;
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/RoleManagerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/RoleManagerCounters.java
new file mode 100644
index 000000000..04d948339
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/RoleManagerCounters.java
@@ -0,0 +1,32 @@
+package net.floodlightcontroller.core.internal;
+
+import net.floodlightcontroller.debugcounter.IDebugCounter;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData;
+
+ public class RoleManagerCounters {
+
+        public final String prefix = RoleManager.class.getSimpleName();
+        public final IDebugCounter setSameRole;
+        public final IDebugCounter setRoleMaster;
+
+        public RoleManagerCounters(IDebugCounterService debugCounters) {
+            debugCounters.registerModule(prefix);
+            setSameRole =
+                    debugCounters.registerCounter(
+                                prefix, "set-same-role",
+                                "Controller received a role request for the same " +
+                                "role the controller already had",
+                                MetaData.WARN);
+
+                setRoleMaster =
+                    debugCounters.registerCounter(
+                                prefix, "set-role-master",
+                                "Controller received a role request with role of " +
+                                "MASTER. This counter can be at most 1.");
+        }
+
+        public String getPrefix(){
+            return this.prefix;
+        }
+    }
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/internal/SwitchEvent.java b/src/main/java/net/floodlightcontroller/core/internal/SwitchEvent.java
new file mode 100644
index 000000000..7a4f36b37
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/SwitchEvent.java
@@ -0,0 +1,18 @@
+package net.floodlightcontroller.core.internal;
+
+import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
+import net.floodlightcontroller.debugevent.IDebugEventService.EventFieldType;
+import org.projectfloodlight.openflow.types.DatapathId;
+
+public class SwitchEvent {
+    @EventColumn(name = "dpid", description = EventFieldType.DPID)
+    DatapathId dpid;
+
+    @EventColumn(name = "reason", description = EventFieldType.STRING)
+    String reason;
+
+    public SwitchEvent(DatapathId dpid, String reason) {
+        this.dpid = dpid;
+        this.reason = reason;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/internal/SwitchManagerCounters.java b/src/main/java/net/floodlightcontroller/core/internal/SwitchManagerCounters.java
new file mode 100644
index 000000000..942809cd4
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/internal/SwitchManagerCounters.java
@@ -0,0 +1,208 @@
+package net.floodlightcontroller.core.internal;
+
+import net.floodlightcontroller.debugcounter.IDebugCounter;
+import net.floodlightcontroller.debugcounter.IDebugCounterService;
+import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData;
+
+public class SwitchManagerCounters {
+
+    public final String prefix = OFSwitchManager.class.getSimpleName();
+    public final IDebugCounter invalidPortsChanged;
+    public final IDebugCounter switchConnected;
+    public final IDebugCounter invalidSwitchActivatedWhileSlave;
+    public final IDebugCounter switchActivated;
+    public final IDebugCounter switchDeactivated;
+    public final IDebugCounter errorActivatedSwitchNotPresent;
+    public final IDebugCounter switchWithSameDpidActivated;
+    public final IDebugCounter switchDisconnected;
+    public final IDebugCounter switchPortChanged;
+    public final IDebugCounter switchOtherChange;
+    public final IDebugCounter switchDisconnectReadTimeout;
+    public final IDebugCounter switchDisconnectHandshakeTimeout;
+    public final IDebugCounter switchDisconnectIOError;
+    public final IDebugCounter switchDisconnectParseError;
+    public final IDebugCounter switchDisconnectSwitchStateException;
+    public final IDebugCounter rejectedExecutionException;
+    public final IDebugCounter switchDisconnectOtherException;
+    public final IDebugCounter unhandledMessage;
+    public final IDebugCounter packetInWhileSwitchIsSlave;
+    public final IDebugCounter roleNotResentBecauseRolePending;
+    public final IDebugCounter epermErrorWhileSwitchIsMaster;
+    public final IDebugCounter roleReplyTimeout;
+    public final IDebugCounter roleReplyReceived;
+    public final IDebugCounter roleReplyErrorUnsupported;
+
+    public SwitchManagerCounters(IDebugCounterService debugCounters) {
+        debugCounters.registerModule(prefix);
+        invalidPortsChanged =
+                debugCounters.registerCounter(
+                            prefix, "invalid-ports-changed",
+                            "Received an unexpected ports changed " +
+                            "notification while the controller was in " +
+                            "SLAVE role.",
+                            MetaData.WARN);
+
+            invalidSwitchActivatedWhileSlave =
+                debugCounters.registerCounter(
+                            prefix, "invalid-switch-activated-while-slave",
+                            "Received an unexpected switchActivated " +
+                            "notification while the controller was in " +
+                            "SLAVE role.",
+                            MetaData.WARN);
+
+            switchActivated =
+                debugCounters.registerCounter(
+                            prefix, "switch-activated",
+                            "A switch connected to this controller is now " +
+                            "in MASTER role");
+
+            switchDeactivated =
+                    debugCounters.registerCounter(
+                                prefix, "switch-activated",
+                                "A switch connected to this controller is now " +
+                                "in SLAVE role");
+
+            errorActivatedSwitchNotPresent = // err
+                debugCounters.registerCounter(
+                            prefix, "error-same-switch-reactivated",
+                            "A switch that was already in active state " +
+                            "was activated again. This indicates a " +
+                            "controller defect",
+                            MetaData.ERROR);
+
+            switchWithSameDpidActivated = // warn
+                debugCounters.registerCounter(
+                            prefix, "switch-with-same-dpid-activated",
+                            "A switch with the same DPID as another switch " +
+                            "connected to the controller. This can be " +
+                            "caused by multiple switches configured with " +
+                            "the same DPID or by a switch reconnecting very " +
+                            "quickly.",
+                            MetaData.WARN);
+
+            switchDisconnected =
+                debugCounters.registerCounter(
+                            prefix, "switch-disconnected",
+                            "FIXME: switch has disconnected");
+
+            switchPortChanged =
+                debugCounters.registerCounter(
+                            prefix, "switch-port-changed",
+                            "Number of times switch ports have changed");
+            switchOtherChange =
+                debugCounters.registerCounter(
+                            prefix, "switch-other-change",
+                            "Number of times other information of a switch " +
+                            "has changed.");
+
+            switchDisconnectReadTimeout =
+                    debugCounters.registerCounter(
+                                prefix, "switch-disconnect-read-timeout",
+                                "Number of times a switch was disconnected due " +
+                                "due the switch failing to send OpenFlow " +
+                                "messages or responding to OpenFlow ECHOs",
+                                MetaData.ERROR);
+                switchDisconnectHandshakeTimeout =
+                    debugCounters.registerCounter(
+                                prefix, "switch-disconnect-handshake-timeout",
+                                "Number of times a switch was disconnected " +
+                                "because it failed to complete the handshake " +
+                                "in time.",
+                                MetaData.ERROR);
+                switchDisconnectIOError =
+                    debugCounters.registerCounter(
+                                prefix, "switch-disconnect-io-error",
+                                "Number of times a switch was disconnected " +
+                                "due to IO errors on the switch connection.",
+                                MetaData.ERROR);
+                switchDisconnectParseError =
+                    debugCounters.registerCounter(
+                                prefix, "switch-disconnect-parse-error",
+                               "Number of times a switch was disconnected " +
+                               "because it sent an invalid packet that could " +
+                               "not be parsed",
+                               MetaData.ERROR);
+
+                switchDisconnectSwitchStateException =
+                    debugCounters.registerCounter(
+                                prefix, "switch-disconnect-switch-state-exception",
+                                "Number of times a switch was disconnected " +
+                                "because it sent messages that were invalid " +
+                                "given the switch connection's state.",
+                                MetaData.ERROR);
+                rejectedExecutionException =
+                    debugCounters.registerCounter(
+                                prefix, "rejected-execution-exception",
+                                "TODO",
+                                MetaData.ERROR);
+
+                switchDisconnectOtherException =
+                    debugCounters.registerCounter(
+                                prefix,  "switch-disconnect-other-exception",
+                                "Number of times a switch was disconnected " +
+                                "due to an exceptional situation not covered " +
+                                "by other counters",
+                                MetaData.ERROR);
+
+                switchConnected =
+                    debugCounters.registerCounter(
+                                prefix, "switch-connected",
+                                "Number of times a new switch connection was " +
+                                "established");
+
+                unhandledMessage =
+                    debugCounters.registerCounter(
+                                prefix, "unhandled-message",
+                                "Number of times an OpenFlow message was " +
+                                "received that the controller ignored because " +
+                                "it was inapproriate given the switch " +
+                                "connection's state.",
+                                MetaData.WARN);
+
+                packetInWhileSwitchIsSlave =
+                        debugCounters.registerCounter(
+                                    prefix, "packet-in-while-switch-is-slave",
+                                    "Number of times a packet in was received " +
+                                    "from a switch that was in SLAVE role. " +
+                                    "Possibly inidicates inconsistent roles.");
+                    epermErrorWhileSwitchIsMaster =
+                        debugCounters.registerCounter(
+                                    prefix, "eperm-error-while-switch-is-master",
+                                    "Number of times a permission error was " +
+                                    "received while the switch was in MASTER role. " +
+                                    "Possibly inidicates inconsistent roles.",
+                                    MetaData.WARN);
+
+                    roleNotResentBecauseRolePending =
+                        debugCounters.registerCounter(
+                                    prefix, "role-not-resent-because-role-pending",
+                                    "The controller tried to reestablish a role " +
+                                    "with a switch but did not do so because a " +
+                                    "previous role request was still pending");
+                    roleReplyTimeout =
+                        debugCounters.registerCounter(
+                                    prefix, "role-reply-timeout",
+                                    "Number of times a role request message did not " +
+                                    "receive the expected reply from a switch",
+                                    MetaData.WARN);
+
+                    roleReplyReceived = // expected RoleReply received
+                        debugCounters.registerCounter(
+                                    prefix, "role-reply-received",
+                                    "Number of times the controller received the " +
+                                    "expected role reply message from a switch");
+
+                    roleReplyErrorUnsupported =
+                        debugCounters.registerCounter(
+                                    prefix, "role-reply-error-unsupported",
+                                    "Number of times the controller received an " +
+                                    "error from a switch in response to a role " +
+                                    "request indicating that the switch does not " +
+                                    "support roles.");
+    }
+
+    public String getPrefix(){
+        return this.prefix;
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/module/ApplicationLoader.java b/src/main/java/net/floodlightcontroller/core/module/ApplicationLoader.java
deleted file mode 100644
index f56dfa996..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/ApplicationLoader.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package net.floodlightcontroller.core.module;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.ObjectReader;
-
-/**
- * Load an application from a configuration directory
- * @author readams
- */
-public class ApplicationLoader 
-    implements IFloodlightModule, IApplicationService {
-    
-    /**
-     * Representation for the application configuration
-     * @author readams
-     */
-    public static class Application {
-        private String name;
-        private String[] modules;
-        private Map<String,String> config;
-
-        public String getName() {
-            return name;
-        }
-        public void setName(String name) {
-            this.name = name;
-        }
-        public String[] getModules() {
-            return modules;
-        }
-        public void setModules(String[] modules) {
-            this.modules = modules;
-        }
-        public Map<String, String> getConfig() {
-            return config;
-        }
-        public void setConfig(Map<String, String> config) {
-            this.config = config;
-        }
-    }
-    
-    
-    protected static Logger logger = 
-            LoggerFactory.getLogger(ApplicationLoader.class);
-    protected static ObjectMapper mapper = new ObjectMapper();
-    protected static ObjectReader reader = mapper.reader(Application.class);
-    
-    IModuleService moduleService;
-    
-    private static String APP_RESOURCE_PATH = "apps/";
-    
-    /**
-     * Path containing application description files
-     */
-    protected String applicationPath;
-
-    /**
-     * Application to load
-     */
-    protected String application;
-
-    // *****************
-    // IFloodlightModule
-    // *****************
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l =
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IApplicationService.class);
-        return l;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-
-        Map<Class<? extends IFloodlightService>,
-        IFloodlightService> m =
-        new HashMap<Class<? extends IFloodlightService>,
-                    IFloodlightService>();
-        // We are the class that implements the service
-        m.put(IApplicationService.class, this);
-        return m;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleDependencies() {
-        return null;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context) 
-            throws FloodlightModuleException {
-        moduleService = context.getServiceImpl(IModuleService.class);
-        
-        Map<String,String> config = context.getConfigParams(this);
-        if (config.containsKey("appsd"))
-            applicationPath = config.get("appsd");
-        if (config.containsKey("application"))
-            application = config.get("application");
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) 
-            throws FloodlightModuleException {
-        if (application == null) {
-            throw new FloodlightModuleException("No application to load");
-        }
-
-        // attempt to load from application path
-        File appPath;
-        if (applicationPath != null && 
-            (appPath = new File(applicationPath)).exists() && 
-            appPath.isDirectory()) {
-            File[] files = appPath.listFiles();
-            Arrays.sort(files);
-            for (File f : files) {
-                if (f.isFile() && f.getName().matches(".*\\.json$"));
-                try {
-                    if (loadApplication(new FileInputStream(f), f.getPath()))
-                        return;
-                } catch (FileNotFoundException e) {
-                    throw new FloodlightModuleException(e);
-                }
-            }
-        }
-
-        // attempt to load from classpath.  Note here that the file needs
-        // to be named after the application to be successful
-        try {
-            String r = APP_RESOURCE_PATH + application + ".json";
-            InputStream is = getClass().getClassLoader().getResourceAsStream(r);
-            loadApplication(is, "resource: " + r);
-        } catch (Exception e) {
-            throw new FloodlightModuleException(e);
-        }
-        
-    }
-
-    private boolean loadApplication(InputStream is, String path) 
-            throws FloodlightModuleException {
-        Application a;
-        try {
-             a = reader.readValue(is);
-        } catch (Exception e) {
-            throw new FloodlightModuleException("Could not read application " + 
-                                                path, e);
-        }
-        if (application.equals(a.getName())) {
-            Properties p = new Properties();
-            if (a.getConfig() != null)
-                p.putAll(a.getConfig());
-            if (a.getModules() != null) {
-                logger.info("Loading application {}", a.getName());
-                moduleService.loadModulesFromList(Arrays.asList(a.getModules()),
-                                                  p);
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleConfigFileNotFoundException.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleConfigFileNotFoundException.java
new file mode 100644
index 000000000..e20d1e06f
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleConfigFileNotFoundException.java
@@ -0,0 +1,10 @@
+package net.floodlightcontroller.core.module;
+
+public class FloodlightModuleConfigFileNotFoundException extends
+    FloodlightModuleException {
+    private static final long serialVersionUID = 1L;
+
+    public FloodlightModuleConfigFileNotFoundException(String fileName) {
+        super("No such file or directory: " + fileName);
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java
deleted file mode 100644
index 27c1f968a..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleContext.java
+++ /dev/null
@@ -1,124 +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.core.module;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The service registry for an IFloodlightProvider.
- * @author alexreimers
- */
-public class FloodlightModuleContext implements IFloodlightModuleContext {
-    protected Map<Class<? extends IFloodlightService>, IFloodlightService> serviceMap;
-    protected Map<Class<? extends IFloodlightModule>, Map<String, String>> configParams;
-    protected Collection<IFloodlightModule> moduleSet;
-    
-    /**
-     * Creates the ModuleContext for use with this IFloodlightProvider.
-     * This will be used as a module registry for all IFloodlightModule(s).
-     */
-    public FloodlightModuleContext() {
-        serviceMap = 
-                new HashMap<Class<? extends IFloodlightService>,
-                                      IFloodlightService>();
-        configParams =
-                new HashMap<Class<? extends IFloodlightModule>,
-                                Map<String, String>>();
-    }
-    
-    /**
-     * Adds a IFloodlightModule for this Context.
-     * @param clazz the service class
-     * @param service The IFloodlightService to add to the registry
-     */
-    public void addService(Class<? extends IFloodlightService> clazz, 
-                           IFloodlightService service) {
-        serviceMap.put(clazz, service);
-    }
-    
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T extends IFloodlightService> T getServiceImpl(Class<T> service) {
-        IFloodlightService s = serviceMap.get(service);
-        return (T)s;
-    }
-    
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getAllServices() {
-        return serviceMap.keySet();
-    }
-    
-    @Override
-    public Collection<IFloodlightModule> getAllModules() {
-        return moduleSet;
-    }
-    
-    public void addModules(Collection<IFloodlightModule> modSet) {
-        if (this.moduleSet == null) 
-            this.moduleSet = new ArrayList<IFloodlightModule>();
-        this.moduleSet.addAll(modSet);
-    }
-
-    @Override
-    public Map<String, String> getConfigParams(IFloodlightModule module) {
-        Class<? extends IFloodlightModule> clazz = module.getClass();
-        return getConfigParams(clazz);
-    }
-
-    @Override
-    public Map<String, String> getConfigParams(Class<? extends IFloodlightModule> clazz) {
-        Map<String, String> retMap = configParams.get(clazz);
-        if (retMap == null) {
-            // Return an empty map if none exists so the module does not
-            // need to null check the map
-            retMap = new HashMap<String, String>();
-            configParams.put(clazz, retMap);
-        }
-
-        // also add any configuration parameters for superclasses, but
-        // only if more specific configuration does not override it
-        for (Class<? extends IFloodlightModule> c : configParams.keySet()) {
-            if (c.isAssignableFrom(clazz)) {
-                for (Map.Entry<String, String> ent : configParams.get(c).entrySet()) {
-                    if (!retMap.containsKey(ent.getKey())) {
-                        retMap.put(ent.getKey(), ent.getValue());
-                    }
-                }
-            }
-        }
-
-        return retMap;
-    }
-    
-    /**
-     * Adds a configuration parameter for a module
-     * @param mod The fully qualified module name to add the parameter to
-     * @param key The configuration parameter key
-     * @param value The configuration parameter value
-     */
-    public void addConfigParam(IFloodlightModule mod, String key, String value) {
-        Map<String, String> moduleParams = configParams.get(mod.getClass());
-        if (moduleParams == null) {
-            moduleParams = new HashMap<String, String>();
-            configParams.put(mod.getClass(), moduleParams);
-        }
-        moduleParams.put(key, value);
-    }
- }
diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java
deleted file mode 100644
index 5cddd37fc..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleException.java
+++ /dev/null
@@ -1,37 +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.core.module;
-
-public class FloodlightModuleException extends Exception {
-	private static final long serialVersionUID = 1L;
-
-	public FloodlightModuleException(String error) {
-		super(error);
-	}
-
-    public FloodlightModuleException() {
-        super();
-    }
-
-    public FloodlightModuleException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public FloodlightModuleException(Throwable cause) {
-        super(cause);
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java
deleted file mode 100644
index 32e4fc031..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/FloodlightModuleLoader.java
+++ /dev/null
@@ -1,501 +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.core.module;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-import java.util.Queue;
-import java.util.ServiceConfigurationError;
-import java.util.ServiceLoader;
-import java.util.Set;
-
-import net.floodlightcontroller.core.annotations.LogMessageDoc;
-import net.floodlightcontroller.core.annotations.LogMessageDocs;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Finds all Floodlight modules in the class path and loads/starts them.
- * @author alexreimers
- *
- */
-public class FloodlightModuleLoader implements IModuleService {
-    protected static Logger logger = 
-            LoggerFactory.getLogger(FloodlightModuleLoader.class);
-
-    protected static Map<Class<? extends IFloodlightService>,
-                  Collection<IFloodlightModule>> serviceMap;
-    protected static Map<IFloodlightModule,
-                  Collection<Class<? extends 
-                                   IFloodlightService>>> moduleServiceMap;
-    protected static Map<String, IFloodlightModule> moduleNameMap;
-    protected static Object lock = new Object();
-
-    protected static Set<String> initedSet = new HashSet<String>();
-    protected static Set<String> startedSet = new HashSet<String>();;
-    
-    protected FloodlightModuleContext floodlightModuleContext;
-    
-    public static final String COMPILED_CONF_FILE = 
-            "floodlightdefault.properties";
-    public static final String FLOODLIGHT_MODULES_KEY =
-            "floodlight.modules";
-    public static final String FLOODLIGHT_CONFD =
-            "floodlight.confd";
-
-    public FloodlightModuleLoader() {
-        floodlightModuleContext = new FloodlightModuleContext();
-        floodlightModuleContext.addService(IModuleService.class, this);
-    }
-    
-    /**
-     * Finds all IFloodlightModule(s) in the classpath. It creates 3 Maps.
-     * serviceMap -> Maps a service to a module
-     * moduleServiceMap -> Maps a module to all the services it provides
-     * moduleNameMap -> Maps the string name to the module
-     * @throws FloodlightModuleException If two modules are specified in the configuration
-     * that provide the same service.
-     */
-    protected static void findAllModules(Collection<String> mList) throws FloodlightModuleException {
-        synchronized (lock) {
-            if (serviceMap != null) return;
-            serviceMap = 
-                    new HashMap<Class<? extends IFloodlightService>,
-                                Collection<IFloodlightModule>>();
-            moduleServiceMap = 
-                    new HashMap<IFloodlightModule,
-                                Collection<Class<? extends 
-                                           IFloodlightService>>>();
-            moduleNameMap = new HashMap<String, IFloodlightModule>();
-            
-            // Get all the current modules in the classpath
-            ClassLoader cl = Thread.currentThread().getContextClassLoader();
-            ServiceLoader<IFloodlightModule> moduleLoader
-                = ServiceLoader.load(IFloodlightModule.class, cl);
-            // Iterate for each module, iterate through and add it's services
-            Iterator<IFloodlightModule> moduleIter = moduleLoader.iterator();
-            while (moduleIter.hasNext()) {
-                IFloodlightModule m = null;
-                try {
-                    m = moduleIter.next();
-                } catch (ServiceConfigurationError sce) {
-                    logger.error("Could not find module: {}", sce.getMessage());
-                    continue;
-                }
-            //}
-            //for (IFloodlightModule m : moduleLoader) {
-                if (logger.isDebugEnabled()) {
-                    logger.debug("Found module " + m.getClass().getName());
-                }
-
-                // Set up moduleNameMap
-                moduleNameMap.put(m.getClass().getCanonicalName(), m);
-
-                // Set up serviceMap
-                Collection<Class<? extends IFloodlightService>> servs =
-                        m.getModuleServices();
-                if (servs != null) {
-                    moduleServiceMap.put(m, servs);
-                    for (Class<? extends IFloodlightService> s : servs) {
-                        Collection<IFloodlightModule> mods = 
-                                serviceMap.get(s);
-                        if (mods == null) {
-                            mods = new ArrayList<IFloodlightModule>();
-                            serviceMap.put(s, mods);
-                        }
-                        mods.add(m);
-                        // Make sure they haven't specified duplicate modules in the config
-                        int dupInConf = 0;
-                        for (IFloodlightModule cMod : mods) {
-                            if (mList.contains(cMod.getClass().getCanonicalName()))
-                                dupInConf += 1;
-                        }
-                        
-                        if (dupInConf > 1) {
-                            String duplicateMods = "";
-                            for (IFloodlightModule mod : mods) {
-                                duplicateMods += mod.getClass().getCanonicalName() + ", ";
-                            }
-                            throw new FloodlightModuleException("ERROR! The configuraiton" +
-                                    " file specifies more than one module that provides the service " +
-                                    s.getCanonicalName() +". Please specify only ONE of the " +
-                                    "following modules in the config file: " + duplicateMods);
-                        }
-                    }
-                }
-            }
-        }
-    }
-    
-    /**
-     * Loads the modules from a specified configuration file.
-     * @param fName The configuration file path
-     * @return An IFloodlightModuleContext with all the modules to be started
-     * @throws FloodlightModuleException
-     */
-    @LogMessageDocs({
-        @LogMessageDoc(level="INFO",
-                message="Loading modules from file {file name}",
-                explanation="The controller is initializing its module " +
-                        "configuration from the specified properties file"),
-        @LogMessageDoc(level="INFO",
-                message="Loading default modules",
-                explanation="The controller is initializing its module " +
-                        "configuration to the default configuration"),
-        @LogMessageDoc(level="ERROR",
-                message="Could not load module configuration file",
-                explanation="The controller failed to read the " +
-                        "module configuration file",
-                recommendation="Verify that the module configuration is " +
-                        "present. " + LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level="ERROR",
-                message="Could not load default modules",
-                explanation="The controller failed to read the default " +
-                        "module configuration",
-                recommendation=LogMessageDoc.CHECK_CONTROLLER)
-    })
-    public IFloodlightModuleContext loadModulesFromConfig(String fName) 
-            throws FloodlightModuleException {
-        Properties prop = new Properties();
-        Collection<String> configMods;
-        
-        File f = new File(fName);
-        if (f.isFile()) {
-            logger.info("Loading modules from file {}", f.getPath());
-            configMods = loadProperties(null, f, prop);
-        } else {
-            logger.info("Loading default modules");
-            InputStream is = this.getClass().getClassLoader().
-                                    getResourceAsStream(COMPILED_CONF_FILE);
-            configMods = loadProperties(is, null, prop);
-        }
-
-        return loadModulesFromList(configMods, prop);
-    }
-    
-    private Collection<String> loadProperties(InputStream is, 
-                                              File confFile, 
-                                              Properties prop) {
-        try {
-            Properties fprop = new Properties();
-            if (is != null) {
-                fprop.load(is);
-            } else {
-                fprop.load(new FileInputStream(confFile));
-            }
-            prop.putAll(fprop);
-        } catch (Exception e) {
-            logger.error("Could not load module configuration file", e);
-            System.exit(1);
-        }
-        
-        Collection<String> configMods = new ArrayList<String>();
-        String moduleList = prop.getProperty(FLOODLIGHT_MODULES_KEY);
-        if (moduleList != null) {
-            moduleList = moduleList.replaceAll("\\s", "");
-            configMods.addAll(Arrays.asList(moduleList.split(",")));
-            prop.remove(FLOODLIGHT_MODULES_KEY);
-        }
-
-        String confdStr = prop.getProperty(FLOODLIGHT_CONFD);
-        prop.remove(FLOODLIGHT_CONFD);
-        if (confdStr != null) {
-            File confd = new File(confdStr);
-            if (confd.exists() && confd.isDirectory()) {
-                File[] files = confd.listFiles();
-                Arrays.sort(files);
-                for (File f : files) {
-                    if (f.isFile() && 
-                        f.getName().matches(".*\\.properties$"))
-                        configMods.addAll(loadProperties(null, f, prop));
-                }
-            }
-        }
-
-        return configMods;
-    }
-    
-    /**
-     * Loads modules (and their dependencies) specified in the list
-     * @param mList The array of fully qualified module names
-     * @param ignoreList The list of Floodlight services NOT to 
-     * load modules for. Used for unit testing.
-     * @return The ModuleContext containing all the loaded modules
-     * @throws FloodlightModuleException
-     */
-    protected IFloodlightModuleContext loadModulesFromList(Collection<String> configMods, Properties prop, 
-            Collection<IFloodlightService> ignoreList) throws FloodlightModuleException {
-        logger.debug("Starting module loader");
-        if (logger.isDebugEnabled() && ignoreList != null)
-            logger.debug("Not loading module services " + ignoreList.toString());
-
-        findAllModules(configMods);
-        
-        Collection<IFloodlightModule> moduleSet = new ArrayList<IFloodlightModule>();
-        Map<Class<? extends IFloodlightService>, IFloodlightModule> moduleMap =
-                new HashMap<Class<? extends IFloodlightService>,
-                            IFloodlightModule>();
-
-        Queue<String> moduleQ = new LinkedList<String>();
-        // Add the explicitly configured modules to the q
-        moduleQ.addAll(configMods);
-        Set<String> modsVisited = new HashSet<String>();
-        
-        while (!moduleQ.isEmpty()) {
-            String moduleName = moduleQ.remove();
-            if (modsVisited.contains(moduleName))
-                continue;
-            modsVisited.add(moduleName);
-            IFloodlightModule module = moduleNameMap.get(moduleName);
-            if (module == null) {
-                throw new FloodlightModuleException("Module " + 
-                        moduleName + " not found");
-            }
-            // If the module provides a service that is in the
-            // services ignorelist don't load it.
-            if ((ignoreList != null) && (module.getModuleServices() != null)) {
-                for (IFloodlightService ifs : ignoreList) {
-                    for (Class<?> intsIgnore : ifs.getClass().getInterfaces()) {
-                        //System.out.println(intsIgnore.getName());
-                        // Check that the interface extends IFloodlightService
-                        //if (intsIgnore.isAssignableFrom(IFloodlightService.class)) {
-                        //System.out.println(module.getClass().getName());
-                        if (intsIgnore.isAssignableFrom(module.getClass())) {
-                            // We now ignore loading this module.
-                            logger.debug("Not loading module " + 
-                                         module.getClass().getCanonicalName() +
-                                         " because interface " +
-                                         intsIgnore.getCanonicalName() +
-                                         " is in the ignore list.");
-                            
-                            continue;
-                        }
-                        //}
-                    }
-                }
-            }
-            
-            // Add the module to be loaded
-            addModule(moduleMap, moduleSet, module);
-            // Add it's dep's to the queue
-            Collection<Class<? extends IFloodlightService>> deps = 
-                    module.getModuleDependencies();
-            if (deps != null) {
-                for (Class<? extends IFloodlightService> c : deps) {
-                    IFloodlightModule m = moduleMap.get(c);
-                    if (m == null) {
-                        Collection<IFloodlightModule> mods = serviceMap.get(c);
-                        // Make sure only one module is loaded
-                        if ((mods == null) || (mods.size() == 0)) {
-                            throw new FloodlightModuleException("ERROR! Could not " +
-                                    "find an IFloodlightModule that provides service " +
-                                    c.toString());
-                        } else if (mods.size() == 1) {
-                            IFloodlightModule mod = mods.iterator().next();
-                            if (!modsVisited.contains(mod.getClass().getCanonicalName()))
-                                moduleQ.add(mod.getClass().getCanonicalName());
-                        } else {
-                            boolean found = false;
-                            for (IFloodlightModule moduleDep : mods) {
-                                if (configMods.contains(moduleDep.getClass().getCanonicalName())) {
-                                    // Module will be loaded, we can continue
-                                    found = true;
-                                    break;
-                                }
-                            }
-                            if (!found) {
-                                String duplicateMods = "";
-                                for (IFloodlightModule mod : mods) {
-                                    duplicateMods += mod.getClass().getCanonicalName() + ", ";
-                                }
-                                throw new FloodlightModuleException("ERROR! Found more " + 
-                                    "than one (" + mods.size() + ") IFloodlightModules that provides " +
-                                    "service " + c.toString() + 
-                                    ". This service is required for " + moduleName + 
-                                    ". Please specify one of the following modules in the config: " + 
-                                    duplicateMods);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        
-        floodlightModuleContext.addModules(moduleSet);
-        parseConfigParameters(prop);
-        initModules(moduleSet);
-        startupModules(moduleSet);
-        
-        return floodlightModuleContext;
-    }
-    
-    @Override
-    public IFloodlightModuleContext loadModulesFromList(Collection<String> configMods, Properties prop) 
-            throws FloodlightModuleException {
-        return loadModulesFromList(configMods, prop, null);
-    }
-    
-    /**
-     * Add a module to the set of modules to load and register its services
-     * @param moduleMap the module map
-     * @param moduleSet the module set
-     * @param module the module to add
-     */
-    protected void addModule(Map<Class<? extends IFloodlightService>, 
-                                           IFloodlightModule> moduleMap,
-                            Collection<IFloodlightModule> moduleSet,
-                            IFloodlightModule module) {
-        if (!moduleSet.contains(module)) {
-            Collection<Class<? extends IFloodlightService>> servs =
-                    moduleServiceMap.get(module);
-            if (servs != null) {
-                for (Class<? extends IFloodlightService> c : servs)
-                    moduleMap.put(c, module);
-            }
-            moduleSet.add(module);
-        }
-    }
-
-    /**
-     * Allocate  service implementations and then init all the modules
-     * @param moduleSet The set of modules to call their init function on
-     * @throws FloodlightModuleException If a module can not properly be loaded
-     */
-    protected void initModules(Collection<IFloodlightModule> moduleSet) 
-                                           throws FloodlightModuleException {
-        for (IFloodlightModule module : moduleSet) {
-            if (initedSet.contains(module.getClass().getCanonicalName()))
-                continue;
-            
-            // Get the module's service instance(s)
-            Map<Class<? extends IFloodlightService>, 
-                IFloodlightService> simpls = module.getServiceImpls();
-
-            // add its services to the context
-            if (simpls != null) {
-                for (Entry<Class<? extends IFloodlightService>, 
-                        IFloodlightService> s : simpls.entrySet()) {
-                    if (logger.isDebugEnabled()) {
-                        logger.debug("Setting " + s.getValue() + 
-                                     "  as provider for " + 
-                                     s.getKey().getCanonicalName());
-                    }
-                    if (floodlightModuleContext.getServiceImpl(s.getKey()) == null) {
-                        floodlightModuleContext.addService(s.getKey(),
-                                                           s.getValue());
-                    } else {
-                        throw new FloodlightModuleException("Cannot set "
-                                                            + s.getValue()
-                                                            + " as the provider for "
-                                                            + s.getKey().getCanonicalName()
-                                                            + " because "
-                                                            + floodlightModuleContext.getServiceImpl(s.getKey())
-                                                            + " already provides it");
-                    }
-                }
-            }
-        }
-        
-        for (IFloodlightModule module : moduleSet) {
-            if (initedSet.contains(module.getClass().getCanonicalName()))
-                continue;
-            initedSet.add(module.getClass().getCanonicalName());
-            
-            // init the module
-            if (logger.isDebugEnabled()) {
-                logger.debug("Initializing " + 
-                             module.getClass().getCanonicalName());
-            }
-            module.init(floodlightModuleContext);
-        }
-    }
-    
-    /**
-     * Call each loaded module's startup method
-     * @param moduleSet the module set to start up
-     * @throws FloodlightModuleException 
-     */
-    protected void startupModules(Collection<IFloodlightModule> moduleSet) 
-            throws FloodlightModuleException {
-        for (IFloodlightModule m : moduleSet) {
-            if (startedSet.contains(m.getClass().getCanonicalName()))
-                continue;
-            startedSet.add(m.getClass().getCanonicalName());
-
-            if (logger.isDebugEnabled()) {
-                logger.debug("Starting " + m.getClass().getCanonicalName());
-            }
-            m.startUp(floodlightModuleContext);
-        }
-    }
-    
-    /**
-     * Parses configuration parameters for each module
-     * @param prop The properties file to use
-     */
-    @LogMessageDoc(level="WARN",
-                   message="Module {module} not found or loaded. " +
-                           "Not adding configuration option {key} = {value}",
-                   explanation="Ignoring a configuration parameter for a " +
-                        "module that is not loaded.")
-    protected void parseConfigParameters(Properties prop) {
-        if (prop == null) return;
-        
-        Enumeration<?> e = prop.propertyNames();
-        while (e.hasMoreElements()) {
-            String key = (String) e.nextElement();
-            // Ignore module list key
-            if (key.equals(FLOODLIGHT_MODULES_KEY)) {
-                continue;
-            }
-            
-            String configValue = null;
-            int lastPeriod = key.lastIndexOf(".");
-            String moduleName = key.substring(0, lastPeriod);
-            String configKey = key.substring(lastPeriod + 1);
-            // Check to see if it's overridden on the command line
-            String systemKey = System.getProperty(key);
-            if (systemKey != null) {
-                configValue = systemKey;
-            } else {
-                configValue = prop.getProperty(key);
-            }
-            
-            IFloodlightModule mod = moduleNameMap.get(moduleName);
-            if (mod == null) {
-                logger.warn("Module {} not found or loaded. " +
-                            "Not adding configuration option {} = {}", 
-                            new Object[]{moduleName, configKey, configValue});
-            } else {
-                floodlightModuleContext.addConfigParam(mod, configKey, configValue);
-            }
-        }
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightModulePriority.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightModulePriority.java
new file mode 100644
index 000000000..d2e561fbf
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightModulePriority.java
@@ -0,0 +1,58 @@
+/**
+ *    Copyright 2013, Big Switch Networks, Inc.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+
+package net.floodlightcontroller.core.module;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Set a module priority value so if there are multiple modules that provide
+ * a given service, and there is a unique module with maximum priority,
+ * we will use that module in preference to lower-priority modules rather
+ * than requiring users to manually specify a module to load.  This makes it
+ * possible to define a default provider that uses the DEFAULT_PROVIDER priority
+ * while the normal modules omit the annotation or specify NORMAL priority.
+ * @author readams
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface FloodlightModulePriority {
+    public enum Priority {
+        MINIMUM(0),
+        TEST(10),
+        EXTRA_LOW(20),
+        LOW(30),
+        NORMAL(40),
+        DEFAULT_PROVIDER(50),
+        HIGH(60),
+        EXTRA_HIGH(70);
+
+        private final int value;
+        
+        private Priority(int value) {
+            this.value = value;
+        }
+
+        public int value() {
+            return value;
+        }
+    }
+
+    public Priority value() default Priority.NORMAL;
+}
diff --git a/src/main/java/net/floodlightcontroller/core/module/FloodlightServices.java b/src/main/java/net/floodlightcontroller/core/module/FloodlightServices.java
new file mode 100644
index 000000000..c5d24b723
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/module/FloodlightServices.java
@@ -0,0 +1,5 @@
+package net.floodlightcontroller.core.module;
+
+public @interface FloodlightServices {
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/module/IApplicationService.java b/src/main/java/net/floodlightcontroller/core/module/IApplicationService.java
deleted file mode 100644
index 60a916930..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/IApplicationService.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.floodlightcontroller.core.module;
-
-public interface IApplicationService extends IFloodlightService {
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java
deleted file mode 100644
index 982e4be26..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModule.java
+++ /dev/null
@@ -1,92 +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.core.module;
-
-import java.util.Collection;
-import java.util.Map;
-
-
-/**
- * Defines an interface for loadable Floodlight modules.
- * 
- * At a high level, these functions are called in the following order:
- * <ol>
- * <li> getServices() : what services does this module provide
- * <li> getDependencies() : list the dependencies
- * <li> init() : internal initializations (don't touch other modules)
- * <li> startUp() : external initializations (<em>do</em> touch other modules)
- * </ol>
- * 
- * @author alexreimers
- */
-public interface IFloodlightModule {
-    
-    /**
-     * Return the list of interfaces that this module implements.
-     * All interfaces must inherit IFloodlightService
-     * @return
-     */
-    
-    public Collection<Class<? extends IFloodlightService>> getModuleServices();
-    
-    /**
-     * Instantiate (as needed) and return objects that implement each
-     * of the services exported by this module.  The map returned maps
-     * the implemented service to the object.  The object could be the
-     * same object or different objects for different exported services.
-     * @return The map from service interface class to service implementation
-     */
-    public Map<Class<? extends IFloodlightService>,
-               IFloodlightService> getServiceImpls();
-    
-    /**
-     * Get a list of Modules that this module depends on.  The module system
-     * will ensure that each these dependencies is resolved before the 
-     * subsequent calls to init().
-     * @return The Collection of IFloodlightServices that this module depends
-     *         on.
-     */
-    
-    public Collection<Class<? extends IFloodlightService>> getModuleDependencies();
-    
-    /**
-     * This is a hook for each module to do its <em>internal</em> initialization, 
-     * e.g., call setService(context.getService("Service"))
-     * 
-     * All module dependencies are resolved when this is called, but not every module 
-     * is initialized.
-     * 
-     * @param context
-     * @throws FloodlightModuleException
-     */
-    
-    void init(FloodlightModuleContext context) throws FloodlightModuleException;
-    
-    /**
-     * This is a hook for each module to do its <em>external</em> initializations,
-     * e.g., register for callbacks or query for state in other modules
-     * 
-     * It is expected that this function will not block and that modules that want
-     * non-event driven CPU will spawn their own threads.
-     * 
-     * @param context
-     * @throws FloodlightModuleException 
-     */
-    
-    void startUp(FloodlightModuleContext context) 
-            throws FloodlightModuleException; 
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java
deleted file mode 100644
index 46dea092c..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/IFloodlightModuleContext.java
+++ /dev/null
@@ -1,59 +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.core.module;
-
-import java.util.Collection;
-import java.util.Map;
-
-	
-public interface IFloodlightModuleContext {	
-    /**
-     * Retrieves a casted version of a module from the registry.
-     * @param name The IFloodlightService object type
-     * @return The IFloodlightService
-     * @throws FloodlightModuleException If the module was not found 
-     * or a ClassCastException was encountered.
-     */
-    public <T extends IFloodlightService> T getServiceImpl(Class<T> service);
-    
-    /**
-     * Returns all loaded services
-     * @return A collection of service classes that have been loaded
-     */
-    public Collection<Class<? extends IFloodlightService>> getAllServices();
-    
-    /**
-     * Returns all loaded modules
-     * @return All Floodlight modules that are going to be loaded
-     */
-    public Collection<IFloodlightModule> getAllModules();
-
-    /**
-     * Gets module specific configuration parameters.
-     * @param module The module to get the configuration parameters for
-     * @return A key, value map of the configuration options
-     */
-    public Map<String, String> getConfigParams(IFloodlightModule module);
-
-    /**
-     * Gets module specific configuration parameters.
-     * @param clazz The class of the module to get configuration parameters for
-     * @return A key, value map of the configuration options
-     */
-    public Map<String, String> getConfigParams(Class<? extends
-                                                     IFloodlightModule> clazz);
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java b/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java
deleted file mode 100644
index 4a5f4ca65..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/IFloodlightService.java
+++ /dev/null
@@ -1,27 +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.core.module;
-
-/**
- * This is the base interface for any IFloodlightModule package that provides 
- * a service.
- * @author alexreimers
- *
- */
-public abstract interface IFloodlightService {
-    // This space is intentionally left blank....don't touch it
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/IModuleService.java b/src/main/java/net/floodlightcontroller/core/module/IModuleService.java
deleted file mode 100644
index 440ad2de6..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/IModuleService.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package net.floodlightcontroller.core.module;
-
-import java.util.Collection;
-import java.util.Properties;
-
-public interface IModuleService extends IFloodlightService {
-    /**
-     * Loads modules (and their dependencies) specified in the list.
-     * @param configMods The collection of fully qualified module names to load.
-     * @param prop The list of properties that are configuration options.
-     * @return The ModuleContext containing all the loaded modules.
-     * @throws FloodlightModuleException
-     */
-    public IFloodlightModuleContext 
-        loadModulesFromList(Collection<String> configMods, 
-                            Properties prop) throws FloodlightModuleException; 
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/ModuleLoaderResource.java b/src/main/java/net/floodlightcontroller/core/module/ModuleLoaderResource.java
deleted file mode 100644
index b4406117e..000000000
--- a/src/main/java/net/floodlightcontroller/core/module/ModuleLoaderResource.java
+++ /dev/null
@@ -1,120 +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.core.module;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Returns list of modules loaded by Floodlight.
- * @author Rob Sherwood
- */
-public class ModuleLoaderResource extends ServerResource {
-    protected static Logger log = 
-            LoggerFactory.getLogger(ModuleLoaderResource.class);
-    
-    /**
-     * Retrieves information about loaded modules.
-     * @return Information about loaded modules.
-     */
-    @Get("json")
-    public Map<String, Object> retrieve() {
-    	return retrieveInternal(false);
-    }
-    
-    /**
-     * Retrieves all modules and their dependencies available
-     * to Floodlight.
-     * @param loadedOnly Whether to return all modules available or only the ones loaded.
-     * @return Information about modules available or loaded.
-     */
-    public Map<String, Object> retrieveInternal(boolean loadedOnly) {    
-        Map<String, Object> model = new HashMap<String, Object>();
-
-        Set<String> loadedModules = new HashSet<String>();
-        for (Object val : getContext().getAttributes().values()) {
-        	if ((val instanceof IFloodlightModule) || (val instanceof IFloodlightService)) {
-        		String serviceImpl = val.getClass().getCanonicalName();
-        		loadedModules.add(serviceImpl);
-        		// log.debug("Tracking serviceImpl " + serviceImpl);
-        	}
-        }
-
-        for (String moduleName : 
-        				FloodlightModuleLoader.moduleNameMap.keySet() ) {
-        	Map<String,Object> moduleInfo = new HashMap<String, Object>();
-
-        	IFloodlightModule module = 
-        				FloodlightModuleLoader.moduleNameMap.get(
-        						moduleName);
-        		
-        	Collection<Class<? extends IFloodlightService>> deps = 
-        			module.getModuleDependencies();
-        	if ( deps == null)
-            	deps = new HashSet<Class<? extends IFloodlightService>>();
-        	Map<String,Object> depsMap = new HashMap<String, Object> ();
-        	for (Class<? extends IFloodlightService> service : deps) {
-        		Object serviceImpl = getContext().getAttributes().get(service.getCanonicalName());
-        		if (serviceImpl != null)
-        			depsMap.put(service.getCanonicalName(), serviceImpl.getClass().getCanonicalName());
-        		else
-        			depsMap.put(service.getCanonicalName(), "<unresolved>");
-
-        	}
-            moduleInfo.put("depends", depsMap);
-        	
-            Collection<Class<? extends IFloodlightService>> provides = 
-            		module.getModuleServices();
-        	if ( provides == null)
-            	provides = new HashSet<Class<? extends IFloodlightService>>();
-        	Map<String,Object> providesMap = new HashMap<String,Object>();
-        	for (Class<? extends IFloodlightService> service : provides) {
-        		providesMap.put(service.getCanonicalName(), module.getServiceImpls().get(service).getClass().getCanonicalName());
-        	}
-        	moduleInfo.put("provides", providesMap);            		
-
-    		moduleInfo.put("loaded", false);	// not loaded, by default
-
-        	// check if this module is loaded directly
-        	if (loadedModules.contains(module.getClass().getCanonicalName())) {
-        		moduleInfo.put("loaded", true);  			
-        	} else {
-        		// if not, then maybe one of the services it exports is loaded
-        		for (Class<? extends IFloodlightService> service : provides) {
-        			String modString = module.getServiceImpls().get(service).getClass().getCanonicalName();
-        			if (loadedModules.contains(modString))
-                		moduleInfo.put("loaded", true);
-        			/* else 
-        				log.debug("ServiceImpl not loaded " + modString); */
-        		}
-        	}
-
-        	if ((Boolean)moduleInfo.get("loaded")|| !loadedOnly )
-        		model.put(moduleName, moduleInfo);
-        }            
-        return model;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/module/Run.java b/src/main/java/net/floodlightcontroller/core/module/Run.java
new file mode 100644
index 000000000..4bf8a2ed4
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/module/Run.java
@@ -0,0 +1,20 @@
+package net.floodlightcontroller.core.module;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicate the run() method of a floodlight module
+ * @author readams
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Run {
+    /** declares this run method as the application main method. Will be called last and is not expected to
+     *  return. It is a configuration error to have more than one module declaring a main method.
+     * @return
+     */
+    boolean mainLoop() default false;
+}
diff --git a/src/main/java/net/floodlightcontroller/core/rest/AggregateStatistics.java b/src/main/java/net/floodlightcontroller/core/rest/AggregateStatistics.java
new file mode 100644
index 000000000..3d0fe680e
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/rest/AggregateStatistics.java
@@ -0,0 +1,39 @@
+package net.floodlightcontroller.core.rest;
+
+import org.projectfloodlight.openflow.protocol.OFAggregateStatsReply;
+import org.projectfloodlight.openflow.types.U64;
+
+public class AggregateStatistics {
+
+    private final U64 packetCount;
+    private final U64 byteCount;
+    private final long flowCount;
+
+    private AggregateStatistics(U64 packetCount, U64 byteCount, long flowCount) {
+        this.packetCount = packetCount;
+        this.byteCount = byteCount;
+        this.flowCount = flowCount;
+    }
+
+    public static AggregateStatistics of(U64 packetCount, U64 byteCount,
+            long flowCount) {
+        return new AggregateStatistics(packetCount, byteCount, flowCount);
+    }
+
+    public static AggregateStatistics of(OFAggregateStatsReply statsReply) {
+        return new AggregateStatistics(statsReply.getPacketCount(),
+                statsReply.getByteCount(), statsReply.getFlowCount());
+    }
+
+    public U64 getPacketCount() {
+        return packetCount;
+    }
+
+    public U64 getByteCount() {
+        return byteCount;
+    }
+
+    public long getFlowCount() {
+        return flowCount;
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/rest/SwitchRepresentation.java b/src/main/java/net/floodlightcontroller/core/rest/SwitchRepresentation.java
new file mode 100644
index 000000000..03a46f462
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/rest/SwitchRepresentation.java
@@ -0,0 +1,116 @@
+package net.floodlightcontroller.core.rest;
+
+import java.net.SocketAddress;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+
+import net.floodlightcontroller.core.IOFConnection;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler;
+import org.projectfloodlight.openflow.protocol.OFCapabilities;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.types.DatapathId;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * REST representation of an OF Switch. Stitches together data from different
+ * areas of the platform to provide a complete, centralized representation.
+ * @author Jason Parraga <Jason.Parraga@bigswitch.com>
+ *
+ */
+public class SwitchRepresentation {
+
+    private final long buffers;
+    private final Set<OFCapabilities> capabilities;
+    private final Short tables;
+    private final SocketAddress inetAddress;
+    private final Collection<OFPortDesc> sortedPorts;
+    private final boolean isConnected;
+    private final Date connectedSince;
+    private final DatapathId dpid;
+    private final Map<Object, Object> attributes;
+    private final boolean isActive;
+
+    private final Collection<IOFConnection> connections;
+    private final String handshakeState;
+    private final String quarantineReason;
+
+    public SwitchRepresentation(@Nonnull IOFSwitch sw, @Nonnull OFSwitchHandshakeHandler handshakeHandler) {
+        Preconditions.checkNotNull(sw, "switch must not be null");
+        Preconditions.checkNotNull(handshakeHandler, "handshakeHandler must not be null");
+
+        // IOFSwitch
+        this.buffers = sw.getBuffers();
+        this.capabilities = sw.getCapabilities();
+        this.tables = sw.getTables();
+        this.inetAddress = sw.getInetAddress();
+        this.sortedPorts = sw.getSortedPorts();
+        this.isConnected = sw.isConnected();
+        this.connectedSince = sw.getConnectedSince();
+        this.dpid = sw.getId();
+        this.attributes = sw.getAttributes();
+        this.isActive = sw.isActive();
+
+        // OFSwitchHandshakeHandler
+        this.connections = handshakeHandler.getConnections();
+        this.handshakeState = handshakeHandler.getState();
+        this.quarantineReason = handshakeHandler.getQuarantineReason();
+    }
+
+    public long getBuffers() {
+        return this.buffers;
+    }
+
+    public Short getTables() {
+        return this.tables;
+    }
+
+    public Set<OFCapabilities> getCapabilities() {
+        return this.capabilities;
+    }
+
+    public SocketAddress getInetAddress() {
+        return this.inetAddress;
+    }
+
+    public Collection<OFPortDesc> getSortedPorts() {
+        return this.sortedPorts;
+    }
+
+    public boolean isConnected() {
+        return this.isConnected;
+    }
+
+    public Date getConnectedSince() {
+        return this.connectedSince;
+    }
+
+    public DatapathId getDpid() {
+        return this.dpid;
+    }
+
+    public Map<Object, Object> getAttributes() {
+        return this.attributes;
+    }
+
+    public boolean isActive() {
+        return this.isActive;
+    }
+
+    public Collection<IOFConnection> getConnections() {
+        return this.connections;
+    }
+
+    public String getHandshakeState() {
+        return this.handshakeState;
+    }
+
+    public String getQuarantineReason() {
+        return this.quarantineReason;
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/rest/TableStatistics.java b/src/main/java/net/floodlightcontroller/core/rest/TableStatistics.java
new file mode 100644
index 000000000..480ff2004
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/rest/TableStatistics.java
@@ -0,0 +1,45 @@
+package net.floodlightcontroller.core.rest;
+
+import org.projectfloodlight.openflow.protocol.OFTableStatsEntry;
+import org.projectfloodlight.openflow.types.TableId;
+import org.projectfloodlight.openflow.types.U64;
+
+public class TableStatistics {
+
+    private final TableId tableId;
+    private final long activeCount;
+    private final U64 lookupCount;
+    private final U64 matchedCount;
+
+    private TableStatistics(TableId tableId, long activeCount, U64 lookupCount, U64 matchedCount) {
+        this.tableId = tableId;
+        this.activeCount = activeCount;
+        this.lookupCount = lookupCount;
+        this.matchedCount = matchedCount;
+    }
+
+    public static TableStatistics of(TableId tableId, long activeCount, U64 lookupCount, U64 matchedCount) {
+        return new TableStatistics(tableId, activeCount, lookupCount, matchedCount);
+    }
+
+    public static TableStatistics of(OFTableStatsEntry entry) {
+        return new TableStatistics(entry.getTableId(),
+                entry.getActiveCount(), entry.getLookupCount(), entry.getMatchedCount());
+    }
+
+    public TableId getTableId() {
+        return tableId;
+    }
+
+    public long getActiveCount() {
+        return activeCount;
+    }
+
+    public U64 getLookupCount() {
+        return lookupCount;
+    }
+
+    public U64 getMatchedCount() {
+        return matchedCount;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/core/types/SwitchMessagePair.java b/src/main/java/net/floodlightcontroller/core/types/SwitchMessagePair.java
index 0e91bc9b4..2f4053296 100644
--- a/src/main/java/net/floodlightcontroller/core/types/SwitchMessagePair.java
+++ b/src/main/java/net/floodlightcontroller/core/types/SwitchMessagePair.java
@@ -17,7 +17,7 @@
 
 package net.floodlightcontroller.core.types;
 
-import org.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFMessage;
 
 import net.floodlightcontroller.core.IOFSwitch;
 
diff --git a/src/main/java/net/floodlightcontroller/core/util/URIUtil.java b/src/main/java/net/floodlightcontroller/core/util/URIUtil.java
new file mode 100644
index 000000000..01a44ccf0
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/util/URIUtil.java
@@ -0,0 +1,10 @@
+package net.floodlightcontroller.core.util;
+
+import java.net.URI;
+
+public class URIUtil {
+
+    public static URI createURI(String hostname, int port) {
+        return URI.create("tcp://" + hostname + ":" + port);
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java
index c957e6356..cea740239 100644
--- a/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/AllSwitchStatisticsResource.java
@@ -25,10 +25,12 @@ import java.util.Map;
 import java.util.Set;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
-import org.openflow.protocol.OFFeaturesReply;
-import org.openflow.protocol.statistics.OFStatistics;
-import org.openflow.protocol.statistics.OFStatisticsType;
-import org.openflow.util.HexString;
+
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.util.HexString;
 import org.restlet.resource.Get;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -50,26 +52,26 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase {
     public Map<String, Object> retrieveInternal(String statType) {
         HashMap<String, Object> model = new HashMap<String, Object>();
 
-        OFStatisticsType type = null;
+        OFStatsType type = null;
         REQUESTTYPE rType = null;
 
         if (statType.equals("port")) {
-            type = OFStatisticsType.PORT;
+            type = OFStatsType.PORT;
             rType = REQUESTTYPE.OFSTATS;
         } else if (statType.equals("queue")) {
-            type = OFStatisticsType.QUEUE;
+            type = OFStatsType.QUEUE;
             rType = REQUESTTYPE.OFSTATS;
         } else if (statType.equals("flow")) {
-            type = OFStatisticsType.FLOW;
+            type = OFStatsType.FLOW;
             rType = REQUESTTYPE.OFSTATS;
         } else if (statType.equals("aggregate")) {
-            type = OFStatisticsType.AGGREGATE;
+            type = OFStatsType.AGGREGATE;
             rType = REQUESTTYPE.OFSTATS;
         } else if (statType.equals("desc")) {
-            type = OFStatisticsType.DESC;
+            type = OFStatsType.DESC;
             rType = REQUESTTYPE.OFSTATS;
         } else if (statType.equals("table")) {
-            type = OFStatisticsType.TABLE;
+            type = OFStatsType.TABLE;
             rType = REQUESTTYPE.OFSTATS;
         } else if (statType.equals("features")) {
             rType = REQUESTTYPE.OFFEATURES;
@@ -80,11 +82,11 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase {
         IFloodlightProviderService floodlightProvider =
                 (IFloodlightProviderService)getContext().getAttributes().
                     get(IFloodlightProviderService.class.getCanonicalName());
-        Set<Long> switchDpids = floodlightProvider.getAllSwitchDpids();
+        Set<DatapathId> switchDpids = floodlightProvider.getAllSwitchDpids();
         List<GetConcurrentStatsThread> activeThreads = new ArrayList<GetConcurrentStatsThread>(switchDpids.size());
         List<GetConcurrentStatsThread> pendingRemovalThreads = new ArrayList<GetConcurrentStatsThread>();
         GetConcurrentStatsThread t;
-        for (Long l : switchDpids) {
+        for (DatapathId l : switchDpids) {
             t = new GetConcurrentStatsThread(l, rType, type);
             activeThreads.add(t);
             t.start();
@@ -98,9 +100,9 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase {
             for (GetConcurrentStatsThread curThread : activeThreads) {
                 if (curThread.getState() == State.TERMINATED) {
                     if (rType == REQUESTTYPE.OFSTATS) {
-                        model.put(HexString.toHexString(curThread.getSwitchId()), curThread.getStatisticsReply());
+                        model.put(HexString.toHexString(curThread.getSwitchId().getLong()), curThread.getStatisticsReply());
                     } else if (rType == REQUESTTYPE.OFFEATURES) {
-                        model.put(HexString.toHexString(curThread.getSwitchId()), curThread.getFeaturesReply());
+                        model.put(HexString.toHexString(curThread.getSwitchId().getLong()), curThread.getFeaturesReply());
                     }
                     pendingRemovalThreads.add(curThread);
                 }
@@ -130,13 +132,13 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase {
     }
 
     protected class GetConcurrentStatsThread extends Thread {
-        private List<OFStatistics> switchReply;
-        private long switchId;
-        private OFStatisticsType statType;
+        private List<OFStatsReply> switchReply;
+        private DatapathId switchId;
+        private OFStatsType statType;
         private REQUESTTYPE requestType;
         private OFFeaturesReply featuresReply;
 
-        public GetConcurrentStatsThread(long switchId, REQUESTTYPE requestType, OFStatisticsType statType) {
+        public GetConcurrentStatsThread(DatapathId switchId, REQUESTTYPE requestType, OFStatsType statType) {
             this.switchId = switchId;
             this.requestType = requestType;
             this.statType = statType;
@@ -144,7 +146,7 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase {
             this.featuresReply = null;
         }
 
-        public List<OFStatistics> getStatisticsReply() {
+        public List<OFStatsReply> getStatisticsReply() {
             return switchReply;
         }
 
@@ -152,7 +154,7 @@ public class AllSwitchStatisticsResource extends SwitchResourceBase {
             return featuresReply;
         }
 
-        public long getSwitchId() {
+        public DatapathId getSwitchId() {
             return switchId;
         }
 
diff --git a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java
index eeaebe22c..457cc91c2 100644
--- a/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/ControllerSwitchesResource.java
@@ -23,14 +23,16 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Collection;
+import java.util.Set;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.ImmutablePort;
 import net.floodlightcontroller.util.FilterIterator;
 
-import org.openflow.protocol.OFPhysicalPort;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.protocol.OFCapabilities;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.protocol.OFActionType;
 import org.restlet.data.Form;
 import org.restlet.data.Status;
 import org.restlet.resource.Get;
@@ -52,7 +54,7 @@ public class ControllerSwitchesResource extends ServerResource {
             this.sw = sw;
         }
 
-        public int getActions() {
+        public Set<OFActionType> getActions() {
             return sw.getActions();
         }
 
@@ -83,11 +85,11 @@ public class ControllerSwitchesResource extends ServerResource {
             return rv;
         }
 
-        public int getBuffers() {
+        public long getBuffers() {
             return sw.getBuffers();
         }
 
-        public int getCapabilities() {
+        public Set<OFCapabilities> getCapabilities() {
             return sw.getCapabilities();
         }
 
@@ -114,8 +116,8 @@ public class ControllerSwitchesResource extends ServerResource {
             return addr.toString();
         }
 
-        public Collection<OFPhysicalPort> getPorts() {
-            return ImmutablePort.ofPhysicalPortListOf(sw.getPorts());
+        public Collection<OFPortDesc> getPorts() {
+            return sw.getPorts();
         }
     }
 
@@ -158,13 +160,13 @@ public class ControllerSwitchesResource extends ServerResource {
                 (IFloodlightProviderService)getContext().getAttributes().
                     get(IFloodlightProviderService.class.getCanonicalName());
 
-        Long switchDPID = null;
+        DatapathId switchDPID = null;
 
         Form form = getQuery();
         String dpid = form.getFirstValue("dpid", true);
         if (dpid != null) {
             try {
-                switchDPID = HexString.toLong(dpid);
+                switchDPID = DatapathId.of(dpid);
             } catch (Exception e) {
                 setStatus(Status.CLIENT_ERROR_BAD_REQUEST, DPID_ERROR);
                 return null;
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java
index 34aa2eaa7..f8f9ff0e6 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterCategoriesResource.java
@@ -23,7 +23,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.types.DatapathId;
 import org.restlet.resource.Get;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
@@ -47,8 +47,8 @@ public class SwitchCounterCategoriesResource extends CounterResourceBase {
         String layer = (String) getRequestAttributes().get("layer");
 
         if (switchID.equalsIgnoreCase("all")) {
-            for (Long dpid : floodlightProvider.getAllSwitchDpids()) {
-                switchID = HexString.toHexString(dpid);
+            for (DatapathId dpid : floodlightProvider.getAllSwitchDpids()) {
+                switchID = dpid.toString();
 
                 getOneSwitchCounterCategoriesJson(model, switchID, counterName, layer);
             }
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java
index 34755ea08..f078dd8c1 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchCounterResource.java
@@ -22,7 +22,7 @@ import java.net.URLDecoder;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.types.DatapathId;
 import org.restlet.resource.Get;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
@@ -46,8 +46,8 @@ public class SwitchCounterResource extends CounterResourceBase {
 
         if (switchID.equalsIgnoreCase("all")) {
             getOneSwitchCounterJson(model, ICounterStoreService.CONTROLLER_NAME, counterName);
-            for (Long dpid : floodlightProvider.getAllSwitchDpids()) {
-                switchID = HexString.toHexString(dpid);
+            for (DatapathId dpid : floodlightProvider.getAllSwitchDpids()) {
+                switchID = dpid.toString();
 
                 getOneSwitchCounterJson(model, switchID, counterName);
             }
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
index 6b4a46318..aa48eb3c1 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java
@@ -26,17 +26,23 @@ import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.annotations.LogMessageDoc;
 
-import org.openflow.protocol.OFFeaturesReply;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFStatisticsRequest;
-import org.openflow.protocol.statistics.OFAggregateStatisticsRequest;
-import org.openflow.protocol.statistics.OFFlowStatisticsRequest;
-import org.openflow.protocol.statistics.OFPortStatisticsRequest;
-import org.openflow.protocol.statistics.OFQueueStatisticsRequest;
-import org.openflow.protocol.statistics.OFStatistics;
-import org.openflow.protocol.statistics.OFStatisticsType;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
+import org.projectfloodlight.openflow.protocol.OFMatch;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFAggregateStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFAggregateStatsReply;
+import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFPortStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFQueueStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.util.HexString;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+import org.projectfloodlight.openflow.types.DatapathId;
 import org.restlet.resource.ResourceException;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
@@ -67,21 +73,34 @@ public class SwitchResourceBase extends ServerResource {
                    		"from the switch",
                    recommendation=LogMessageDoc.CHECK_SWITCH + " " +
                    		LogMessageDoc.GENERIC_ACTION)
-    protected List<OFStatistics> getSwitchStatistics(long switchId,
-                                                     OFStatisticsType statType) {
+    protected List<OFStatsReply> getSwitchStatistics(DatapathId switchId,
+                                                     OFStatsType statType) {
         IFloodlightProviderService floodlightProvider =
                 (IFloodlightProviderService)getContext().getAttributes().
                     get(IFloodlightProviderService.class.getCanonicalName());
 
         IOFSwitch sw = floodlightProvider.getSwitch(switchId);
-        Future<List<OFStatistics>> future;
-        List<OFStatistics> values = null;
-        if (sw != null) {
-            OFStatisticsRequest req = new OFStatisticsRequest();
-            req.setStatisticType(statType);
+        
+        OFFactory factory = OFFactories.getFactory(OFVersion.OF_13);
+        OFFlowStatsRequest flowStatsRequest = factory.buildFlowStatsRequest()
+            .build();
+        
+        Future<List<OFFlowStatsReply>> future = sw.queryStatistics(flowStatsRequest);
+        return future.get();
+        
+        
+        sw.get
+        
+        Future<List<OFStatsReply>> future;
+        List<OFStatsReply> values = null;
+        if (sw != null) 
+        	{
+        	OFFactory
+            OFStatsRequest<> req = new OFFactory.
+            req.cre(statType);
             int requestLength = req.getLengthU();
-            if (statType == OFStatisticsType.FLOW) {
-                OFFlowStatisticsRequest specificReq = new OFFlowStatisticsRequest();
+            if (statType == OFStatsType.FLOW) {
+                OFStatsRequest specificReq = new OFFlowStatisticsRequest();
                 OFMatch match = new OFMatch();
                 match.setWildcards(0xffffffff);
                 specificReq.setMatch(match);
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchRoleResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchRoleResource.java
index e6d66e2c2..d7b4c0129 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchRoleResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchRoleResource.java
@@ -18,7 +18,7 @@ package net.floodlightcontroller.core.web;
 
 import java.util.HashMap;
 
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.types.DatapathId;
 import org.restlet.resource.ServerResource;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
@@ -53,7 +53,7 @@ public class SwitchRoleResource extends ServerResource {
             return model;
         }
 
-        Long dpid = HexString.toLong(switchId);
+        DatapathId dpid = DatapathId.of(switchId);
         IOFSwitch sw = floodlightProvider.getSwitch(dpid);
         if (sw == null)
             return null;
diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
index 57771f718..a70d120ae 100644
--- a/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/SwitchStatisticsResource.java
@@ -20,7 +20,8 @@ package net.floodlightcontroller.core.web;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.openflow.protocol.statistics.OFStatisticsType;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.types.DatapathId;
 import org.restlet.resource.Get;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -42,17 +43,17 @@ public class SwitchStatisticsResource extends SwitchResourceBase {
         String statType = (String) getRequestAttributes().get("statType");
         
         if (statType.equals("port")) {
-            values = getSwitchStatistics(switchId, OFStatisticsType.PORT);
+            values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.PORT);
         } else if (statType.equals("queue")) {
-            values = getSwitchStatistics(switchId, OFStatisticsType.QUEUE);
+            values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.QUEUE);
         } else if (statType.equals("flow")) {
-            values = getSwitchStatistics(switchId, OFStatisticsType.FLOW);
+            values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.FLOW);
         } else if (statType.equals("aggregate")) {
-            values = getSwitchStatistics(switchId, OFStatisticsType.AGGREGATE);
+            values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.AGGREGATE);
         } else if (statType.equals("desc")) {
-            values = getSwitchStatistics(switchId, OFStatisticsType.DESC);
+            values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.DESC);
         } else if (statType.equals("table")) {
-            values = getSwitchStatistics(switchId, OFStatisticsType.TABLE);
+            values = getSwitchStatistics(DatapathId.of(switchId), OFStatsType.TABLE);
         } else if (statType.equals("features")) {
             values = getSwitchFeaturesReply(switchId);
         }
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java
index ce4d3ba3c..f5f3aea8c 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/ByteArrayMACSerializer.java
@@ -23,7 +23,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializerProvider;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.util.HexString;
 
 /**
  * Serialize a MAC as colon-separated hexadecimal
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java
index 6df067ead..d07a25468 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/DPIDSerializer.java
@@ -23,7 +23,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializerProvider;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.util.HexString;
 
 /**
  * Serialize a DPID as colon-separated hexadecimal
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java
index c797681ed..c7ea09b83 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/MACSerializer.java
@@ -23,7 +23,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializerProvider;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.util.HexString;
 
 /**
  * Serialize a MAC as colon-separated hexadecimal
diff --git a/src/main/java/net/floodlightcontroller/counter/CounterStore.java b/src/main/java/net/floodlightcontroller/counter/CounterStore.java
index bfe3b963f..d3067e60d 100644
--- a/src/main/java/net/floodlightcontroller/counter/CounterStore.java
+++ b/src/main/java/net/floodlightcontroller/counter/CounterStore.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
@@ -33,8 +34,10 @@ import net.floodlightcontroller.counter.CounterValue.CounterType;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPv4;
 
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.types.DatapathId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -69,12 +72,12 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService {
         }
 
     protected class CounterKeyTuple {
-        byte msgType;
-        long dpid;
+        OFType msgType;
+        DatapathId dpid;
         short l3type;
         byte l4type;
 
-        public CounterKeyTuple(byte msgType, long dpid, short l3type, byte l4type){
+        public CounterKeyTuple(OFType msgType, DatapathId dpid, short l3type, byte l4type){
             this.msgType = msgType;
             this.dpid = dpid;
             this.l3type = l3type;
@@ -99,8 +102,8 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService {
         public int hashCode() {
             final int prime = 283;
             int result = 1;
-            result = prime * result + msgType;
-            result = prime * result + (int) (dpid ^ (dpid >>> 32));
+            result = prime * result + msgType.hashCode();
+            result = prime * result + (int) (dpid.getLong() ^ (dpid.getLong() >>> 32));
             result = prime * result + l3type;
             result = prime * result + l4type;
             return result;
@@ -155,7 +158,7 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService {
 
     @Override
     public void updatePacketInCountersLocal(IOFSwitch sw, OFMessage m, Ethernet eth) {
-        if (((OFPacketIn)m).getPacketData().length <= 0) {
+        if (((OFPacketIn)m).getData().length <= 0) {
             return;
         }
         CounterKeyTuple countersKey = this.getCountersKey(sw, m, eth);
@@ -291,7 +294,7 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService {
     //*******************************
 
     protected CounterKeyTuple getCountersKey(IOFSwitch sw, OFMessage m, Ethernet eth) {
-        byte mtype = m.getType().getTypeValue();
+        OFType mtype = m.getType();
         short l3type = 0;
         byte l4type = 0;
 
@@ -322,7 +325,7 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService {
         int l3type = eth.getEtherType() & 0xffff;
         String switchIdHex = sw.getStringId();
         String etherType = String.format("%04x", eth.getEtherType());
-        String packetName = m.getType().toClass().getName();
+        String packetName = m.getType().getClass().getName();
         packetName = packetName.substring(packetName.lastIndexOf('.')+1);
 
         // L2 Type
@@ -470,7 +473,7 @@ public class CounterStore implements IFloodlightModule, ICounterStoreService {
 
         /* String values for names */
         String switchIdHex = sw.getStringId();
-        String packetName = m.getType().toClass().getName();
+        String packetName = m.getType().getClass().getName();
         packetName = packetName.substring(packetName.lastIndexOf('.')+1);
 
         String controllerFMCounterName =
diff --git a/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java b/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java
index c0cbd5591..79bf4548d 100644
--- a/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java
+++ b/src/main/java/net/floodlightcontroller/counter/ICounterStoreService.java
@@ -19,7 +19,7 @@ package net.floodlightcontroller.counter;
 import java.util.List;
 import java.util.Map;
 
-import org.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFMessage;
 
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.IFloodlightService;
diff --git a/src/main/java/net/floodlightcontroller/counter/NullCounterStore.java b/src/main/java/net/floodlightcontroller/counter/NullCounterStore.java
index bdcc690b3..eff67dcac 100644
--- a/src/main/java/net/floodlightcontroller/counter/NullCounterStore.java
+++ b/src/main/java/net/floodlightcontroller/counter/NullCounterStore.java
@@ -23,7 +23,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFMessage;
 
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/CounterNode.java b/src/main/java/net/floodlightcontroller/debugcounter/CounterNode.java
new file mode 100644
index 000000000..8da964aa2
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugcounter/CounterNode.java
@@ -0,0 +1,338 @@
+package net.floodlightcontroller.debugcounter;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.TreeMap;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * A node in the counter hierarchy tree. We use a single tree and "merge" the
+ * counter modules into this single tree.
+ *
+ * <li> Adding modules or counters to the tree must happen at the root of the tree.
+ * <li> The root and the first level of the tree (root and module) are a shim
+ * layers that con't have an actual counter value. We represent this with a
+ * null counter.
+ *
+ * @author gregor
+ */
+class CounterNode implements Iterable<DebugCounterImpl> {
+    private static final String QUOTED_SEP = Pattern.quote("/");
+
+    /** path/hierarchy of this counter without leading /. An empty string
+     * represents the root. A string without a / is a module name
+     */
+    private final String hierarchy;
+    /**
+     * The path/hierarchy elements split into a list
+     */
+    private final List<String> hierarchyElements;
+    /**
+     * The actual counter instance for this node. Can be null for
+     * root level and module level.
+     */
+    private final DebugCounterImpl counter;
+    private final TreeMap<String,CounterNode> children = new TreeMap<>();
+
+    /**
+     * convert module name and counter hierarchy into list of
+     * hierarchy elements
+     * @param moduleName
+     * @param counterHierarchy
+     * @return
+     */
+    static List<String>
+    getHierarchyElements(String moduleName, String counterHierarchy) {
+        DebugCounterServiceImpl.verifyModuleNameSanity(moduleName);
+        List<String> ret = new ArrayList<>();
+        ret.add(moduleName);
+        if (counterHierarchy == null || counterHierarchy.isEmpty()) {
+            return ret;
+        }
+        for (String element: counterHierarchy.split(QUOTED_SEP)) {
+            ret.add(element);
+        }
+        return ret;
+    }
+
+    private CounterNode(List<String> hierarchyElements,
+                        DebugCounterImpl counter) {
+        super();
+        this.hierarchyElements = ImmutableList.copyOf(hierarchyElements);
+        this.hierarchy = Joiner.on("/").join(hierarchyElements);
+        this.counter = counter;
+    }
+
+    /**
+     * Create a new counter hierarchy tree and return the root
+     * @return
+     */
+    public static CounterNode newTree() {
+        return new CounterNode(ImmutableList.<String>of(), null);
+    }
+
+    /** verify that this node is the root */
+    private void verifyIsRoot() {
+        if (hierarchyElements.size() != 0) {
+            throw new IllegalStateException("This not is not the root. Can "
+                    + "only call addCounter() on the root node. Current node: "
+                    + hierarchy);
+        }
+    }
+
+
+
+    /**
+     *  return the full hierarchy as string, including module name
+     */
+    @Nonnull
+    String getHierarchy() {
+        return hierarchy;
+    }
+
+    /**
+     * @return the list of hierarchy elements for this node
+     */
+    @Nonnull
+    List<String> getHierarchyElements() {
+        return hierarchyElements;
+    }
+
+    /**
+     * @return this node's counters
+     */
+    @Nullable
+    DebugCounterImpl getCounter() {
+        return counter;
+    }
+
+    /**
+     * Reset this counter all counter below it in the hierarchy
+     */
+    void resetHierarchy() {
+        for (DebugCounterImpl cur: this) {
+            cur.reset();
+        }
+    }
+
+    /**
+     * Return an Iterable over all DebugCounterImpls at and below this
+     * node. Note we return an Iterable<DebugCounterImpls> not
+     * Iterable<IDebugCounter> on purpose.
+     * @return
+     */
+    Iterable<DebugCounterImpl> getCountersInHierarchy() {
+        return this;
+    }
+
+
+    /**
+     * Lookup the CounterNode identified by the hieraryElements if it exists.
+     * Returns null if no such CounterNode is found. Must only be called on
+     * the root of the tree.
+     * @param hierarchyElements
+     * @return
+     */
+    CounterNode lookup(List<String> hierarchyElements) {
+        CounterNode cur = this;
+        for (String element: hierarchyElements) {
+            cur = cur.children.get(element);
+            if (cur == null) {
+                break;
+            }
+        }
+        return cur;
+    }
+
+    /**
+     * Add the given moduleName to the tree. Can only be called on the root.
+     * If the module already exists, the all counters of the module will
+     * be reset.
+     * @param moduleName
+     * @return true if the module was newly added, false if the module already
+     * existed
+     */
+    boolean addModule(@Nonnull String moduleName) {
+        verifyIsRoot();
+        if (children.containsKey(moduleName)) {
+            children.get(moduleName).resetHierarchy();
+            return false;
+        } else {
+            CounterNode newNode =
+                    new CounterNode(ImmutableList.of(moduleName), null);
+            children.put(moduleName, newNode);
+            return true;
+        }
+    }
+
+    /**
+     * Add the given Counter to the hierarchy. If the counterHierarcy already
+     * exists, reset the hierarchy
+     * @param counter
+     * @return null if the counterHierarchy is newly registered, otherwise
+     * returns the already registered DebugCounterImpl instance
+     * @throws IllegalArgumentException if the parent of the counter does not
+     * yet exist
+     */
+    @Nullable
+    DebugCounterImpl addCounter(@Nonnull DebugCounterImpl counter) {
+        verifyIsRoot();
+        ArrayList<String> path = new ArrayList<>();
+        path.add(counter.getModuleName());
+        for (String element: counter.getCounterHierarchy().split(QUOTED_SEP)) {
+            path.add(element);
+        }
+        String newCounterName = path.get(path.size()-1);
+
+        CounterNode parent = lookup(path.subList(0, path.size()-1));
+        if (parent == null) {
+            throw new IllegalArgumentException("Missing hierarchy level for "
+                    + "counter: " + counter.getModuleName() + " "
+                    + counter.getCounterHierarchy());
+        }
+        if (parent.children.containsKey(newCounterName)) {
+            CounterNode old = parent.children.get(newCounterName);
+            // FIXME: we should check that old and new has the same
+            // description and meta-data, otherwise we should probably thrown
+            // and exception and refuse the operation.
+            old.resetHierarchy();
+            return old.counter;
+        } else {
+            CounterNode newNode = new CounterNode(path, counter);
+            parent.children.put(newCounterName, newNode);
+            return counter;
+        }
+    }
+
+
+    /**
+     * Iterator over the counters in the counter hierarchy.
+     * Iteration order is a pre-order tree walk. Children of a node are
+     * visited in sorted order.
+     * @author gregor
+     */
+    private final static class CounterIterator implements Iterator<DebugCounterImpl> {
+        // NOTE: since some counters
+        ArrayDeque<CounterNode> stack = new ArrayDeque<>();
+        CounterNode curNode = null;
+        private CounterIterator(CounterNode root) {
+            stack.push(root);
+            gotoNextNode();
+        }
+
+        private void gotoNextNode() {
+            while (true) {
+                curNode = null;
+                if (stack.isEmpty()) {
+                    break;
+                }
+                curNode = stack.pop();
+                for (CounterNode child: curNode.children.descendingMap().values()) {
+                    stack.push(child);
+                }
+                if (curNode.counter != null) {
+                    break;
+                }
+            }
+        }
+
+        @Override
+        public boolean hasNext() {
+            return curNode != null;
+        }
+
+        @Override
+        public DebugCounterImpl next() {
+            if (curNode == null) {
+                throw new NoSuchElementException();
+            }
+            DebugCounterImpl ret = curNode.counter;
+            gotoNextNode();
+            return ret;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Override
+    public Iterator<DebugCounterImpl> iterator() {
+        return new CounterIterator(this);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result
+                 + ((children == null) ? 0 : children.hashCode());
+        result = prime * result
+                 + ((counter == null) ? 0 : counter.hashCode());
+        result = prime * result
+                 + ((hierarchy == null) ? 0 : hierarchy.hashCode());
+        result = prime
+                 * result
+                 + ((hierarchyElements == null) ? 0
+                                               : hierarchyElements.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        CounterNode other = (CounterNode) obj;
+        if (children == null) {
+            if (other.children != null) return false;
+        } else if (!children.equals(other.children)) return false;
+        if (counter == null) {
+            if (other.counter != null) return false;
+        } else if (!counter.equals(other.counter)) return false;
+        if (hierarchy == null) {
+            if (other.hierarchy != null) return false;
+        } else if (!hierarchy.equals(other.hierarchy)) return false;
+        if (hierarchyElements == null) {
+            if (other.hierarchyElements != null) return false;
+        } else if (!hierarchyElements.equals(other.hierarchyElements))
+                                                                      return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        return toString(0);
+    }
+
+    public String toString(int indent) {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < indent; i++) {
+            builder.append(" ");
+        }
+        builder.append("hierarchy=");
+        builder.append(hierarchy);
+        builder.append(", counter=");
+        builder.append(counter);
+        builder.append(", children=");
+        builder.append(children.keySet());
+        builder.append("\n");
+        for (CounterNode child: children.values()) {
+            builder.append(child.toString(indent + 3));
+        }
+        return builder.toString();
+    }
+
+
+
+}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java
deleted file mode 100644
index 5bb1ce167..000000000
--- a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounter.java
+++ /dev/null
@@ -1,741 +0,0 @@
-package net.floodlightcontroller.debugcounter;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-
-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.web.DebugCounterRoutable;
-import net.floodlightcontroller.restserver.IRestApiService;
-
-/**
- * This class implements a central store for all counters used for debugging the
- * system. For counters based on traffic-type, see ICounterStoreService.
- *
- * @author Saurav
- */
-public class DebugCounter implements IFloodlightModule, IDebugCounterService {
-    protected static Logger log = LoggerFactory.getLogger(DebugCounter.class);
-
-    /**
-     * registered counters need a counter id
-     */
-    protected AtomicInteger counterIdCounter = new AtomicInteger();
-
-    /**
-     * The counter value
-     */
-    protected class MutableLong {
-        long value = 0;
-        public void increment() { value += 1; }
-        public void increment(long incr) { value += incr; }
-        public long get() { return value; }
-        public void set(long val) { value = val; }
-      }
-
-    /**
-     * protected class to store counter information
-     */
-    public static class CounterInfo {
-        String moduleCounterHierarchy;
-        String counterDesc;
-        CounterType ctype;
-        String moduleName;
-        String counterHierarchy;
-        int counterId;
-        boolean enabled;
-        String[] metaData;
-
-        public CounterInfo(int counterId, boolean enabled,
-                           String moduleName, String counterHierarchy,
-                           String desc, CounterType ctype, String... metaData) {
-            this.moduleCounterHierarchy = moduleName + "/" + counterHierarchy;
-            this.moduleName = moduleName;
-            this.counterHierarchy = counterHierarchy;
-            this.counterDesc = desc;
-            this.ctype = ctype;
-            this.counterId = counterId;
-            this.enabled = enabled;
-            this.metaData = metaData;
-        }
-
-        public String getModuleCounterHierarchy() { return moduleCounterHierarchy; }
-        public String getCounterDesc() { return counterDesc; }
-        public CounterType getCtype() { return ctype; }
-        public String getModuleName() { return moduleName; }
-        public String getCounterHierarchy() { return counterHierarchy; }
-        public int getCounterId() { return counterId; }
-        public boolean isEnabled() { return enabled; }
-        public String[] getMetaData() { return metaData; }
-    }
-
-    //******************
-    //   Global stores
-    //******************
-
-    /**
-     * Counter info for a debug counter
-     */
-    public class DebugCounterInfo {
-        CounterInfo cinfo;
-        AtomicLong cvalue;
-
-        public DebugCounterInfo(CounterInfo cinfo) {
-            this.cinfo = cinfo;
-            this.cvalue = new AtomicLong();
-        }
-        public CounterInfo getCounterInfo() {
-            return cinfo;
-        }
-        public Long getCounterValue() {
-            return cvalue.get();
-        }
-    }
-
-    /**
-     * Global debug-counter storage across all threads. These are
-     * updated from the local per thread counters by the flush counters method.
-     */
-    protected static DebugCounterInfo[] allCounters =
-                            new DebugCounterInfo[MAX_COUNTERS];
-
-
-    /**
-     * per module counters, indexed by the module name and storing three levels
-     * of Counter information in the form of CounterIndexStore
-     */
-    protected ConcurrentHashMap<String, ConcurrentHashMap<String, CounterIndexStore>>
-        moduleCounters = new ConcurrentHashMap<String,
-                                                ConcurrentHashMap<String,
-                                                                   CounterIndexStore>>();
-
-    protected class CounterIndexStore {
-        int index;
-        Map<String, CounterIndexStore> nextLevel;
-
-        public CounterIndexStore(int index, Map<String,CounterIndexStore> cis) {
-            this.index = index;
-            this.nextLevel = cis;
-        }
-    }
-
-    /**
-     * fast global cache for counter ids that are currently active
-     */
-    protected Set<Integer> currentCounters = Collections.newSetFromMap(
-                                         new ConcurrentHashMap<Integer,Boolean>());
-
-    //******************
-    // Thread local stores
-    //******************
-
-    /**
-     * Thread local storage of counter info
-     */
-    protected class LocalCounterInfo {
-        boolean enabled;
-        MutableLong cvalue;
-
-        public LocalCounterInfo(boolean enabled) {
-            this.enabled = enabled;
-            this.cvalue = new MutableLong();
-        }
-    }
-
-    /**
-     * Thread local debug counters used for maintaining counters local to a thread.
-     */
-    protected final ThreadLocal<LocalCounterInfo[]> threadlocalCounters =
-            new ThreadLocal<LocalCounterInfo[]>() {
-        @Override
-        protected LocalCounterInfo[] initialValue() {
-            return new LocalCounterInfo[MAX_COUNTERS];
-        }
-    };
-
-    /**
-     * Thread local cache for counter ids that are currently active.
-     */
-    protected final ThreadLocal<Set<Integer>> threadlocalCurrentCounters =
-            new ThreadLocal<Set<Integer>>() {
-        @Override
-        protected Set<Integer> initialValue() {
-            return new HashSet<Integer>();
-        }
-    };
-
-    //*******************************
-    //   IDebugCounter
-    //*******************************
-
-    protected class CounterImpl implements IDebugCounter {
-        private final int counterId;
-
-        public CounterImpl(int counterId) {
-            this.counterId = counterId;
-        }
-
-        @Override
-        public void updateCounterWithFlush() {
-            if (!validCounterId()) return;
-            updateCounter(counterId, 1, true);
-        }
-
-        @Override
-        public void updateCounterNoFlush() {
-            if (!validCounterId()) return;
-            updateCounter(counterId, 1, false);
-        }
-
-        @Override
-        public void updateCounterWithFlush(int incr) {
-            if (!validCounterId()) return;
-            updateCounter(counterId, incr, true);
-        }
-
-        @Override
-        public void updateCounterNoFlush(int incr) {
-            if (!validCounterId()) return;
-            updateCounter(counterId, incr, false);
-        }
-
-        @Override
-        public long getCounterValue() {
-            if (!validCounterId()) return -1;
-            return allCounters[counterId].cvalue.get();
-        }
-
-        private boolean validCounterId() {
-            if (counterId < 0 || counterId >= MAX_COUNTERS) {
-                log.error("Invalid counterId invoked");
-                return false;
-            }
-            return true;
-        }
-
-    }
-
-   //*******************************
-   //   IDebugCounterService
-   //*******************************
-
-   @Override
-   public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
-                           String counterDescription, CounterType counterType,
-                           String... metaData)
-               throws MaxCountersRegistered, MaxHierarchyRegistered,
-                      MissingHierarchicalLevel {
-       // check if counter already exists
-       if (!moduleCounters.containsKey(moduleName)) {
-           moduleCounters.putIfAbsent(moduleName,
-                new ConcurrentHashMap<String, CounterIndexStore>());
-       }
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (rci.allLevelsFound) {
-           // counter exists
-           log.info("Counter exists for {}/{} -- resetting counters", moduleName,
-                    counterHierarchy);
-           resetCounterHierarchy(moduleName, counterHierarchy);
-           return new CounterImpl(rci.ctrIds[rci.foundUptoLevel-1]);
-       }
-       // check for validity of counter
-       if (rci.levels.length > MAX_HIERARCHY) {
-           String err = "Registry of counterHierarchy " + counterHierarchy +
-                   " exceeds max hierachy " + MAX_HIERARCHY + ".. aborting";
-           throw new MaxHierarchyRegistered(err);
-       }
-       if (rci.foundUptoLevel < rci.levels.length-1) {
-           String needToRegister = "";
-           for (int i=0; i<=rci.foundUptoLevel; i++) {
-               needToRegister += rci.levels[i];
-           }
-           String err = "Attempting to register hierarchical counterHierarchy " +
-                   counterHierarchy + " but parts of hierarchy missing. " +
-                   "Please register " +  needToRegister + " first";
-           throw new MissingHierarchicalLevel(err);
-       }
-
-       // get a new counter id
-       int counterId = counterIdCounter.getAndIncrement();
-       if (counterId >= MAX_COUNTERS) {
-           throw new MaxCountersRegistered("max counters reached");
-       }
-       // create storage for counter
-       boolean enabled = (counterType == CounterType.ALWAYS_COUNT) ? true : false;
-       CounterInfo ci = new CounterInfo(counterId, enabled, moduleName,
-                                        counterHierarchy, counterDescription,
-                                        counterType, metaData);
-       allCounters[counterId] = new DebugCounterInfo(ci);
-
-       // account for the new counter in the module counter hierarchy
-       addToModuleCounterHierarchy(moduleName, counterId, rci);
-
-       // finally add to active counters
-       if (enabled) {
-           currentCounters.add(counterId);
-       }
-       return new CounterImpl(counterId);
-   }
-
-   private void updateCounter(int counterId, int incr, boolean flushNow) {
-       if (counterId < 0 || counterId >= MAX_COUNTERS) return;
-
-       LocalCounterInfo[] thiscounters =  this.threadlocalCounters.get();
-       if (thiscounters[counterId] == null) {
-           // seeing this counter for the first time in this thread - create local
-           // store by consulting global store
-           DebugCounterInfo dc = allCounters[counterId];
-           if (dc != null) {
-               thiscounters[counterId] = new LocalCounterInfo(dc.cinfo.enabled);
-               if (dc.cinfo.enabled) {
-                   Set<Integer> thisset = this.threadlocalCurrentCounters.get();
-                   thisset.add(counterId);
-               }
-           } else {
-               log.error("updateCounter seen locally for counter {} but no global"
-                          + "storage exists for it yet .. not updating", counterId);
-               return;
-           }
-       }
-
-       // update local store if enabled locally for updating
-       LocalCounterInfo lc = thiscounters[counterId];
-       if (lc.enabled) {
-           lc.cvalue.increment(incr);
-           if (flushNow) {
-               DebugCounterInfo dc = allCounters[counterId];
-               if (dc.cinfo.enabled) {
-                   // globally enabled - flush now
-                   dc.cvalue.addAndGet(lc.cvalue.get());
-                   lc.cvalue.set(0);
-               } else {
-                   // global counter is disabled - don't flush, disable locally
-                   lc.enabled = false;
-                   Set<Integer> thisset = this.threadlocalCurrentCounters.get();
-                   thisset.remove(counterId);
-               }
-           }
-       }
-   }
-
-   @Override
-   public void flushCounters() {
-       LocalCounterInfo[] thiscounters =  this.threadlocalCounters.get();
-       Set<Integer> thisset = this.threadlocalCurrentCounters.get();
-       ArrayList<Integer> temp = new ArrayList<Integer>();
-
-       for (int counterId : thisset) {
-           LocalCounterInfo lc = thiscounters[counterId];
-           if (lc.cvalue.get() > 0) {
-               DebugCounterInfo dc = allCounters[counterId];
-               if (dc.cinfo.enabled) {
-                   // globally enabled - flush now
-                   dc.cvalue.addAndGet(lc.cvalue.get());
-                   lc.cvalue.set(0);
-               } else {
-                   // global counter is disabled - don't flush, disable locally
-                   lc.enabled = false;
-                   temp.add(counterId);
-               }
-           }
-       }
-       for (int cId : temp) {
-           thisset.remove(cId);
-       }
-
-       // At this point it is possible that the thread-local set does not
-       // include a counter that has been enabled and is present in the global set.
-       // We need to sync thread-local currently enabled set of counterIds with
-       // the global set.
-       Sets.SetView<Integer> sv = Sets.difference(currentCounters, thisset);
-       for (int counterId : sv) {
-           if (thiscounters[counterId] != null) {
-               thiscounters[counterId].enabled = true;
-               thisset.add(counterId);
-           }
-       }
-   }
-
-   @Override
-   public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (!rci.allLevelsFound) {
-           String missing = rci.levels[rci.foundUptoLevel];
-           log.error("Cannot reset counter hierarchy - missing counter {}", missing);
-           return;
-       }
-       // reset at this level
-       allCounters[rci.ctrIds[rci.foundUptoLevel-1]].cvalue.set(0);
-       // reset all levels below
-       ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-       for (int index : resetIds) {
-           allCounters[index].cvalue.set(0);
-       }
-   }
-
-   @Override
-   public void resetAllCounters() {
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-       for (String moduleName : moduleCounters.keySet()) {
-           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-           for (int index : resetIds) {
-               allCounters[index].cvalue.set(0);
-           }
-       }
-   }
-
-   @Override
-   public void resetAllModuleCounters(String moduleName) {
-       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-
-       if (target != null) {
-           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-           for (int index : resetIds) {
-               allCounters[index].cvalue.set(0);
-           }
-       } else {
-           if (log.isDebugEnabled())
-               log.debug("No module found with name {}", moduleName);
-       }
-   }
-
-   @Override
-   public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (!rci.allLevelsFound) {
-           String missing = rci.levels[rci.foundUptoLevel];
-           log.error("Cannot enable counter - counter not found {}", missing);
-           return;
-       }
-       // enable specific counter
-       DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]];
-       dc.cinfo.enabled = true;
-       currentCounters.add(dc.cinfo.counterId);
-   }
-
-   @Override
-   public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (!rci.allLevelsFound) {
-           String missing = rci.levels[rci.foundUptoLevel];
-           log.error("Cannot disable counter - counter not found {}", missing);
-           return;
-       }
-       // disable specific counter
-       DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]];
-       if (dc.cinfo.ctype == CounterType.COUNT_ON_DEMAND) {
-           dc.cinfo.enabled = false;
-           dc.cvalue.set(0);
-           currentCounters.remove(dc.cinfo.counterId);
-       }
-   }
-
-   @Override
-   public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
-                                                     String counterHierarchy) {
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       if (!rci.allLevelsFound) {
-           String missing = rci.levels[rci.foundUptoLevel];
-           log.error("Cannot fetch counter - counter not found {}", missing);
-           return Collections.emptyList();
-       }
-       ArrayList<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
-       // get counter and all below it
-       DebugCounterInfo dc = allCounters[rci.ctrIds[rci.foundUptoLevel-1]];
-       dcilist.add(dc);
-       ArrayList<Integer> belowIds = getHierarchyBelow(moduleName, rci);
-       for (int index : belowIds) {
-           dcilist.add(allCounters[index]);
-       }
-       return dcilist;
-   }
-
-   @Override
-   public List<DebugCounterInfo> getAllCounterValues() {
-       List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-
-       for (String moduleName : moduleCounters.keySet()) {
-           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-           for (int index : resetIds) {
-               dcilist.add(allCounters[index]);
-           }
-       }
-       return dcilist;
-   }
-
-   @Override
-   public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
-       List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-
-       if (moduleCounters.containsKey(moduleName)) {
-           ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
-           for (int index : resetIds) {
-               dcilist.add(allCounters[index]);
-           }
-       }
-       return dcilist;
-   }
-
-   @Override
-   public boolean containsModuleCounterHierarchy(String moduleName,
-                                                 String counterHierarchy) {
-       if (!moduleCounters.containsKey(moduleName)) return false;
-       RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
-       return rci.allLevelsFound;
-   }
-
-   @Override
-   public boolean containsModuleName(String moduleName) {
-       return  (moduleCounters.containsKey(moduleName)) ? true : false;
-   }
-
-   @Override
-   public List<String> getModuleList() {
-       List<String> retval = new ArrayList<String>();
-       retval.addAll(moduleCounters.keySet());
-       return retval;
-   }
-
-   @Override
-   public List<String> getModuleCounterList(String moduleName) {
-       if (!moduleCounters.containsKey(moduleName))
-           return Collections.emptyList();
-
-       List<String> retval = new ArrayList<String>();
-       RetCtrInfo rci = new RetCtrInfo();
-       rci.levels = "".split("/");
-
-       ArrayList<Integer> cids = getHierarchyBelow(moduleName, rci);
-       for (int index : cids) {
-           retval.add(allCounters[index].cinfo.counterHierarchy);
-       }
-       return retval;
-   }
-
-   //*******************************
-   //   Internal Methods
-   //*******************************
-
-   protected class RetCtrInfo {
-       boolean allLevelsFound; // counter indices found all the way down the hierarchy
-       boolean hierarchical; // true if counterHierarchy is hierarchical
-       int foundUptoLevel;
-       int[]  ctrIds;
-       String[] levels;
-
-       public RetCtrInfo() {
-           ctrIds = new int[MAX_HIERARCHY];
-           for (int i=0; i<MAX_HIERARCHY; i++) {
-               ctrIds[i] = -1;
-           }
-       }
-
-       @Override
-       public boolean equals(Object oth) {
-           if (!(oth instanceof RetCtrInfo)) return false;
-           RetCtrInfo other = (RetCtrInfo)oth;
-           if (other.allLevelsFound != this.allLevelsFound) return false;
-           if (other.hierarchical != this.hierarchical) return false;
-           if (other.foundUptoLevel != this.foundUptoLevel) return false;
-           if (!Arrays.equals(other.ctrIds, this.ctrIds)) return false;
-           if (!Arrays.equals(other.levels, this.levels)) return false;
-           return true;
-       }
-
-   }
-
-   protected RetCtrInfo getCounterId(String moduleName, String counterHierarchy) {
-       RetCtrInfo rci = new RetCtrInfo();
-       Map<String, CounterIndexStore> templevel = moduleCounters.get(moduleName);
-       rci.levels = counterHierarchy.split("/");
-       if (rci.levels.length > 1) rci.hierarchical = true;
-       if (templevel == null) {
-           log.error("moduleName {} does not exist in debugCounters", moduleName);
-           return rci;
-       }
-
-       /*
-       if (rci.levels.length > MAX_HIERARCHY) {
-           // chop off all array elems greater that MAX_HIERARCHY
-           String[] temp = new String[MAX_HIERARCHY];
-           System.arraycopy(rci.levels, 0, temp, 0, MAX_HIERARCHY);
-           rci.levels = temp;
-       }
-       */
-       for (int i=0; i<rci.levels.length; i++) {
-           if (templevel != null) {
-               CounterIndexStore cis = templevel.get(rci.levels[i]) ;
-               if (cis == null) {
-                   // could not find counterHierarchy part at this level
-                   break;
-               } else {
-                   rci.ctrIds[i] = cis.index;
-                   templevel = cis.nextLevel;
-                   rci.foundUptoLevel++;
-                   if (i == rci.levels.length-1) {
-                       rci.allLevelsFound = true;
-                   }
-               }
-           } else {
-               // there are no more levels, which means that some part of the
-               // counterHierarchy has no corresponding map
-               break;
-           }
-       }
-       return rci;
-   }
-
-   protected void addToModuleCounterHierarchy(String moduleName, int counterId,
-                                            RetCtrInfo rci) {
-       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
-       if (target == null) return;
-       CounterIndexStore cis = null;
-
-       for (int i=0; i<rci.foundUptoLevel; i++) {
-           cis = target.get(rci.levels[i]);
-           target = cis.nextLevel;
-       }
-       if (cis != null) {
-           if (cis.nextLevel == null)
-               cis.nextLevel = new ConcurrentHashMap<String, CounterIndexStore>();
-           cis.nextLevel.put(rci.levels[rci.foundUptoLevel],
-                             new CounterIndexStore(counterId, null));
-       } else {
-           target.put(rci.levels[rci.foundUptoLevel],
-                      new CounterIndexStore(counterId, null));
-       }
-   }
-
-   // given a partial hierarchical counter, return the rest of the hierarchy
-   protected ArrayList<Integer> getHierarchyBelow(String moduleName, RetCtrInfo rci) {
-       Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
-       CounterIndexStore cis = null;
-       ArrayList<Integer> retval = new ArrayList<Integer>();
-       if (target == null) return retval;
-
-       // get to the level given
-       for (int i=0; i<rci.foundUptoLevel; i++) {
-           cis = target.get(rci.levels[i]);
-           target = cis.nextLevel;
-       }
-
-       if (target == null || rci.foundUptoLevel == MAX_HIERARCHY) {
-           // no more levels
-           return retval;
-       } else {
-           // recursively get all ids
-           getIdsAtLevel(target, retval, rci.foundUptoLevel+1);
-       }
-
-       return retval;
-   }
-
-   protected void getIdsAtLevel(Map<String, CounterIndexStore> hcy,
-                                ArrayList<Integer> retval, int level) {
-       if (level > MAX_HIERARCHY) return;
-       if (hcy == null || retval == null) return;
-
-       // Can return the counter names as well but for now ids are enough.
-       for (CounterIndexStore cistemp : hcy.values()) {
-           retval.add(cistemp.index); // value at this level
-           if (cistemp.nextLevel != null) {
-               getIdsAtLevel(cistemp.nextLevel, retval, level+1);
-           }
-       }
-   }
-
-   protected void printAllCounterIds() {
-       log.info("<moduleCounterHierarchy>");
-       Set<String> keys = moduleCounters.keySet();
-       for (String key : keys) {
-           log.info("ModuleName: {}", key);
-           Map<String, CounterIndexStore> lev1 = moduleCounters.get(key);
-           for (String key1 : lev1.keySet()) {
-               CounterIndexStore cis1 = lev1.get(key1);
-               log.info(" L1 {}:{}", key1, new Object[] {cis1.index, cis1.nextLevel});
-               if (cis1.nextLevel != null) {
-                   Map<String, CounterIndexStore> lev2 = cis1.nextLevel;
-                   for (String key2 : lev2.keySet()) {
-                       CounterIndexStore cis2 = lev2.get(key2);
-                       log.info("  L2 {}:{}", key2, new Object[] {cis2.index,
-                                                                  cis2.nextLevel});
-                       if (cis2.nextLevel != null) {
-                           Map<String, CounterIndexStore> lev3 = cis2.nextLevel;
-                           for (String key3 : lev3.keySet()) {
-                               CounterIndexStore cis3 = lev3.get(key3);
-                               log.info("   L3 {}:{}", key3, new Object[] {cis3.index,
-                                                                          cis3.nextLevel});
-                           }
-                       }
-                   }
-               }
-           }
-       }
-       log.info("<\\moduleCounterHierarchy>");
-   }
-
-   //*******************************
-   //   IFloodlightModule
-   //*******************************
-
-   @Override
-   public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-       Collection<Class<? extends IFloodlightService>> l =
-               new ArrayList<Class<? extends IFloodlightService>>();
-       l.add(IDebugCounterService.class);
-       return l;
-   }
-
-   @Override
-   public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
-       Map<Class<? extends IFloodlightService>, IFloodlightService> m =
-               new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
-       m.put(IDebugCounterService.class, this);
-       return m;
-   }
-
-   @Override
-   public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
-       ArrayList<Class<? extends IFloodlightService>> deps =
-               new ArrayList<Class<? extends IFloodlightService>>();
-       deps.add(IRestApiService.class);
-       return deps;
-   }
-
-   @Override
-   public void init(FloodlightModuleContext context) throws FloodlightModuleException {
-
-   }
-
-   @Override
-   public void startUp(FloodlightModuleContext context) {
-       IRestApiService restService =
-               context.getServiceImpl(IRestApiService.class);
-       restService.addRestletRoutable(new DebugCounterRoutable());
-   }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterImpl.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterImpl.java
new file mode 100644
index 000000000..c0aa316d9
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterImpl.java
@@ -0,0 +1,141 @@
+package net.floodlightcontroller.debugcounter;
+
+import java.util.Collection;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.annotation.Nonnull;
+
+import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+
+class DebugCounterImpl implements IDebugCounter {
+    private final String moduleName;
+    private final String counterHierarchy;
+    private final String description;
+    private final ImmutableSet<IDebugCounterService.MetaData> metaData;
+
+    private final AtomicLong value = new AtomicLong();
+
+
+    DebugCounterImpl(@Nonnull String moduleName,
+                     @Nonnull String counterHierarchy,
+                     @Nonnull String description,
+                     @Nonnull Collection<MetaData> metaData) {
+        this.moduleName = moduleName;
+        this.counterHierarchy = counterHierarchy;
+        this.description = description;
+        this.metaData = Sets.immutableEnumSet(metaData);
+    }
+
+    @Nonnull
+    String getModuleName() {
+        return moduleName;
+    }
+
+
+    @Nonnull
+    String getCounterHierarchy() {
+        return counterHierarchy;
+    }
+
+
+    @Nonnull
+    String getDescription() {
+        return description;
+    }
+
+    @Nonnull
+    ImmutableSet<IDebugCounterService.MetaData> getMetaData() {
+        return metaData;
+    }
+
+    public void reset() {
+        value.set(0);
+    }
+
+    @Override
+    public void increment() {
+        value.incrementAndGet();
+    }
+
+    @Override
+    public void add(long increment) {
+        if (increment < 0) {
+            throw new IllegalArgumentException("increment must be > 0. Was "
+                    + increment);
+        }
+        value.addAndGet(increment);
+    }
+
+    @Override
+    public long getCounterValue() {
+        return value.get();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime
+                 * result
+                 + ((counterHierarchy == null) ? 0
+                                              : counterHierarchy.hashCode());
+        result = prime * result
+                 + ((description == null) ? 0 : description.hashCode());
+        result = prime * result
+                 + ((metaData == null) ? 0 : metaData.hashCode());
+        result = prime * result
+                 + ((moduleName == null) ? 0 : moduleName.hashCode());
+        result = prime * result + ((value == null) ? 0 : value.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        DebugCounterImpl other = (DebugCounterImpl) obj;
+        if (counterHierarchy == null) {
+            if (other.counterHierarchy != null) return false;
+        } else if (!counterHierarchy.equals(other.counterHierarchy))
+                                                                    return false;
+        if (description == null) {
+            if (other.description != null) return false;
+        } else if (!description.equals(other.description)) return false;
+        if (metaData == null) {
+            if (other.metaData != null) return false;
+        } else if (!metaData.equals(other.metaData)) return false;
+        if (moduleName == null) {
+            if (other.moduleName != null) return false;
+        } else if (!moduleName.equals(other.moduleName)) return false;
+        if (value == null) {
+            if (other.value != null) return false;
+        } else if (value.get() != other.value.get()) return false;
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("[");
+        builder.append(moduleName);
+        builder.append(" ");
+        builder.append(counterHierarchy);
+        builder.append(", description=");
+        builder.append(description);
+        builder.append(", metaData=");
+        builder.append(metaData);
+        builder.append(", value=");
+        builder.append(value);
+        builder.append("]");
+        return builder.toString();
+    }
+
+
+
+
+}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResource.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResource.java
new file mode 100644
index 000000000..941802c31
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResource.java
@@ -0,0 +1,119 @@
+package net.floodlightcontroller.debugcounter;
+
+import java.util.Set;
+
+import javax.annotation.concurrent.Immutable;
+
+import net.floodlightcontroller.debugcounter.IDebugCounterService.MetaData;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Resource class for DebugCounter
+ * Serves the REST api with dynamic data
+ */
+@Immutable
+public class DebugCounterResource {
+
+    public static final String MODULE_NAME_PREDICATE = "modulename";
+    public static final String HIERARCHY_PREDICATE = "hierarchy";
+    private static final Joiner joiner = Joiner.on(", ");
+
+
+    private final Long counterValue;
+    private final String counterDesc;
+    private final String counterHierarchy;
+    private final String moduleName;
+    private final ImmutableSet<MetaData> metadata;
+    private final String metadataString;
+
+    public DebugCounterResource(DebugCounterImpl counter) {
+        this.moduleName = counter.getModuleName();
+        this.counterHierarchy = counter.getCounterHierarchy();
+        this.counterDesc = counter.getDescription();
+        this.metadata = counter.getMetaData();
+        this.counterValue = counter.getCounterValue();
+        this.metadataString = joiner.join(metadata);
+    }
+
+    public Long getCounterValue() {
+        return counterValue;
+    }
+
+    public String getCounterDesc() {
+        return counterDesc;
+    }
+
+    public String getCounterHierarchy() {
+        return counterHierarchy;
+    }
+
+    public String getModuleName() {
+        return moduleName;
+    }
+
+    public Set<MetaData> getMetadata() {
+        return metadata;
+    }
+
+    public String getMetadataString() {
+        return metadataString;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result
+                 + ((counterDesc == null) ? 0 : counterDesc.hashCode());
+        result = prime
+                 * result
+                 + ((counterHierarchy == null) ? 0
+                                              : counterHierarchy.hashCode());
+        result = prime * result
+                 + ((counterValue == null) ? 0 : counterValue.hashCode());
+        result = prime * result
+                 + ((metadata == null) ? 0 : metadata.hashCode());
+        result = prime
+                 * result
+                 + ((metadataString == null) ? 0 : metadataString.hashCode());
+        result = prime * result
+                 + ((moduleName == null) ? 0 : moduleName.hashCode());
+        return result;
+    }
+
+    /**
+     * Compare all fields, not only the "key" fields
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+        if (obj == null) return false;
+        if (getClass() != obj.getClass()) return false;
+        DebugCounterResource other = (DebugCounterResource) obj;
+        if (counterDesc == null) {
+            if (other.counterDesc != null) return false;
+        } else if (!counterDesc.equals(other.counterDesc)) return false;
+        if (counterHierarchy == null) {
+            if (other.counterHierarchy != null) return false;
+        } else if (!counterHierarchy.equals(other.counterHierarchy))
+                                                                    return false;
+        if (counterValue == null) {
+            if (other.counterValue != null) return false;
+        } else if (!counterValue.equals(other.counterValue)) return false;
+        if (metadata == null) {
+            if (other.metadata != null) return false;
+        } else if (!metadata.equals(other.metadata)) return false;
+        if (metadataString == null) {
+            if (other.metadataString != null) return false;
+        } else if (!metadataString.equals(other.metadataString))
+                                                                return false;
+        if (moduleName == null) {
+            if (other.moduleName != null) return false;
+        } else if (!moduleName.equals(other.moduleName)) return false;
+        return true;
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java
deleted file mode 100644
index 9edd47473..000000000
--- a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterResourceBase.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package net.floodlightcontroller.debugcounter;
-
-import org.restlet.resource.ResourceException;
-import org.restlet.resource.ServerResource;
-
-public class DebugCounterResourceBase extends ServerResource {
-
-    protected IDebugCounterService debugCounter;
-
-    @Override
-    protected void doInit() throws ResourceException {
-        super.doInit();
-        debugCounter = (IDebugCounterService)getContext().getAttributes().
-                get(IDebugCounterService.class.getCanonicalName());
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterServiceImpl.java b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterServiceImpl.java
new file mode 100644
index 000000000..2e2fe499f
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugcounter/DebugCounterServiceImpl.java
@@ -0,0 +1,251 @@
+package net.floodlightcontroller.debugcounter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.GuardedBy;
+
+import org.projectfloodlight.core.IShutdownListener;
+import org.projectfloodlight.core.IShutdownService;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DebugCounterServiceImpl implements IFloodlightModule, IDebugCounterService {
+    protected static final Logger logger =
+            LoggerFactory.getLogger(DebugCounterServiceImpl.class);
+
+    /**
+     * The tree of counters.
+     */
+    private final CounterNode root = CounterNode.newTree();
+
+    /**
+     * protects the counter hierarchy tree. The writeLock is required to
+     * change to hierarchy, i.e., adding nodes. The readLock is required
+     * to query the counters or to reset them.
+     */
+    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+
+    static void verifyStringSanity(String str, String name) {
+        if (str == null) {
+            if (name == null) {
+                throw new NullPointerException();
+            } else {
+                throw new NullPointerException(name + " must not be null");
+            }
+        }
+        if (str.isEmpty()) {
+            if (name == null) {
+                throw new IllegalArgumentException();
+            } else {
+                throw new IllegalArgumentException(name + " must not be empty");
+            }
+        }
+    }
+
+    static void verifyModuleNameSanity(String moduleName) {
+        verifyStringSanity(moduleName, "moduleName");
+        if (moduleName.contains("/")) {
+            throw new IllegalArgumentException("moduleName must not contain /");
+        }
+    }
+
+    @Override
+    public boolean registerModule(String moduleName) {
+        verifyModuleNameSanity(moduleName);
+        lock.writeLock().lock();
+        try {
+            return root.addModule(moduleName);
+        } finally {
+            lock.writeLock().unlock();
+        }
+    }
+
+    @Override
+    public IDebugCounter registerCounter(@Nonnull String moduleName,
+                                         @Nonnull String counterHierarchy,
+                                         @Nonnull String counterDescription,
+                                         @Nonnull MetaData... metaData) {
+        verifyModuleNameSanity(moduleName);
+        verifyStringSanity(counterHierarchy, "counterHierarchy");
+        if (counterDescription == null) {
+            throw new Exception("counterDescription must not be null");
+        }
+        if (metaData == null) {
+            // somebody passing in a null array. sigh.
+            throw new NullPointerException("metaData must not be null");
+        }
+        DebugCounterImpl counter =
+                new DebugCounterImpl(moduleName, counterHierarchy,
+                                     counterDescription,
+                                     Arrays.asList(metaData));
+        lock.writeLock().lock();
+        try {
+            DebugCounterImpl oldCounter = root.addCounter(counter);
+            if (oldCounter != null && logger.isDebugEnabled()) {
+                logger.debug("Counter {} {} already registered. Resetting hierarchy",
+                          moduleName, counterHierarchy);
+            }
+            return oldCounter;
+        } finally {
+            lock.writeLock().unlock();
+        }
+    }
+
+    @GuardedBy("lock.readLock")
+    private boolean resetInternal(List<String> hierarchyElements) {
+        CounterNode node = root.lookup(hierarchyElements);
+        if (node == null) {
+            return false;
+        }
+        node.resetHierarchy();
+        return true;
+    }
+
+    @Override
+    public boolean resetCounterHierarchy(String moduleName,
+                                         String counterHierarchy) {
+        verifyModuleNameSanity(moduleName);
+        verifyStringSanity(counterHierarchy, "counterHierarchy");
+        lock.readLock().lock();
+        try {
+            return resetInternal(CounterNode.getHierarchyElements(moduleName, counterHierarchy));
+        } finally {
+            lock.readLock().unlock();
+        }
+    }
+
+    @Override
+    public void resetAllCounters() {
+        lock.readLock().lock();
+        try {
+            root.resetHierarchy();
+        } finally {
+            lock.readLock().unlock();
+        }
+    }
+
+
+    @Override
+    public boolean resetAllModuleCounters(String moduleName) {
+        verifyModuleNameSanity(moduleName);
+        lock.readLock().lock();
+        try {
+            return resetInternal(Collections.singletonList(moduleName));
+        } finally {
+            lock.readLock().unlock();
+        }
+    }
+
+    @GuardedBy("lock.readLock")
+    private List<DebugCounterResource> getCountersFromNode(CounterNode node) {
+        if (node == null) {
+            return Collections.emptyList();
+        }
+        List<DebugCounterResource> ret = new ArrayList<>();
+        for (DebugCounterImpl counter: node.getCountersInHierarchy()) {
+            ret.add(new DebugCounterResource(counter));
+        }
+        return ret;
+    }
+
+    @Override
+    public List<DebugCounterResource>
+    getCounterHierarchy(String moduleName, String counterHierarchy) {
+        verifyModuleNameSanity(moduleName);
+        verifyStringSanity(counterHierarchy, "counterHierarchy");
+        List<String> hierarchyElements =
+                CounterNode.getHierarchyElements(moduleName, counterHierarchy);
+        lock.readLock().lock();
+        try {
+            return getCountersFromNode(root.lookup(hierarchyElements));
+        } finally {
+            lock.readLock().unlock();
+        }
+    }
+
+    @Override
+    public List<DebugCounterResource> getAllCounterValues() {
+        lock.readLock().lock();
+        try {
+            return getCountersFromNode(root);
+        } finally {
+            lock.readLock().unlock();
+        }
+    }
+
+    @Override
+    public List<DebugCounterResource> getModuleCounterValues(String moduleName) {
+        verifyModuleNameSanity(moduleName);
+        List<String> hierarchyElements = Collections.singletonList(moduleName);
+        lock.readLock().lock();
+        try {
+            return getCountersFromNode(root.lookup(hierarchyElements));
+        } finally {
+            lock.readLock().unlock();
+        }
+    }
+
+    private class ShutdownListenenerDelegate implements IShutdownListener {
+        @Override
+        public void floodlightIsShuttingDown() {
+            for (DebugCounterResource counter: getAllCounterValues()) {
+                logger.info("Module {} counterHierarchy {} value {}",
+                            counter.getModuleName(),
+                            counter.getCounterHierarchy(),
+                            counter.getCounterValue());
+            }
+        }
+    }
+
+
+   //*******************************
+   //   IFloodlightModule
+   //*******************************
+
+   @Override
+   public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+       Collection<Class<? extends IFloodlightService>> l =
+               new ArrayList<Class<? extends IFloodlightService>>();
+       l.add(IDebugCounterService.class);
+       return l;
+   }
+
+   @Override
+   public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+       Map<Class<? extends IFloodlightService>, IFloodlightService> m =
+               new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+       m.put(IDebugCounterService.class, this);
+       return m;
+   }
+
+   @Override
+   public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+       ArrayList<Class<? extends IFloodlightService>> deps =
+               new ArrayList<Class<? extends IFloodlightService>>();
+       deps.add(IShutdownService.class);
+       return deps;
+   }
+
+   @Override
+   public void init(FloodlightModuleContext context) {
+   }
+
+   @Override
+   public void startUp(FloodlightModuleContext context) {
+       IShutdownService shutdownService =
+               context.getServiceImpl(IShutdownService.class);
+       shutdownService.registerShutdownListener(new ShutdownListenenerDelegate());
+   }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounter.java
deleted file mode 100644
index dbde1854e..000000000
--- a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package net.floodlightcontroller.debugcounter;
-
-public interface IDebugCounter {
-    /**
-     * Increments the counter by 1 thread-locally, and immediately flushes to
-     * the global counter storage. This method should be used for counters that
-     * are updated outside the OF message processing pipeline.
-     */
-    void updateCounterWithFlush();
-
-    /**
-     * Increments the counter by 1 thread-locally. Flushing to the global
-     * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
-     * resulting in higher performance. This method should be used for counters
-     * updated in the OF message processing pipeline.
-     */
-    void updateCounterNoFlush();
-
-    /**
-     * Increments the counter thread-locally by the 'incr' specified, and immediately
-     * flushes to the global counter storage. This method should be used for counters
-     * that are updated outside the OF message processing pipeline.
-     */
-    void updateCounterWithFlush(int incr);
-
-    /**
-     * Increments the counter thread-locally by the 'incr' specified. Flushing to the global
-     * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
-     * resulting in higher performance. This method should be used for counters
-     * updated in the OF message processing pipeline.
-     */
-    void updateCounterNoFlush(int incr);
-
-    /**
-     * Retrieve the value of the counter from the global counter store
-     */
-    long getCounterValue();
-}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java b/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java
deleted file mode 100644
index 538e60dad..000000000
--- a/src/main/java/net/floodlightcontroller/debugcounter/IDebugCounterService.java
+++ /dev/null
@@ -1,259 +0,0 @@
-package net.floodlightcontroller.debugcounter;
-
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.debugcounter.DebugCounter.DebugCounterInfo;
-
-import java.util.List;
-
-public interface IDebugCounterService extends IFloodlightService {
-
-    /**
-     * Different counter types. Counters that are meant to be counted-on-demand
-     * need to be separately enabled/disabled.
-     */
-    public enum CounterType {
-        ALWAYS_COUNT,
-        COUNT_ON_DEMAND
-    }
-
-    /**
-     * Debug Counter Qualifiers
-     */
-    public static final String CTR_MDATA_WARN = "warn";
-    public static final String CTR_MDATA_ERROR = "error";
-
-    /**
-     *  A limit on the maximum number of counters that can be created
-     */
-    public static final int MAX_COUNTERS = 5000;
-
-    /**
-     * Exception thrown when MAX_COUNTERS have been registered
-     */
-    public class MaxCountersRegistered extends CounterException {
-        private static final long serialVersionUID = 3173747663719376745L;
-        String errormsg;
-        public MaxCountersRegistered(String errormsg) {
-            this.errormsg = errormsg;
-        }
-        @Override
-        public String getMessage() {
-            return this.errormsg;
-        }
-    }
-    /**
-     * Exception thrown when MAX_HIERARCHY has been reached
-     */
-    public class MaxHierarchyRegistered extends CounterException {
-        private static final long serialVersionUID = 967431358683523871L;
-        String errormsg;
-        public MaxHierarchyRegistered(String errormsg) {
-            this.errormsg = errormsg;
-        }
-        @Override
-        public String getMessage() {
-            return this.errormsg;
-        }
-    }
-    /**
-     * Exception thrown when attempting to register a hierarchical counter
-     * where higher levels of the hierarchy have not been pre-registered
-     */
-    public class MissingHierarchicalLevel extends CounterException {
-        private static final long serialVersionUID = 517315311533995739L;
-        String errormsg;
-        public MissingHierarchicalLevel(String errormsg) {
-            this.errormsg = errormsg;
-        }
-        @Override
-        public String getMessage() {
-            return this.errormsg;
-        }
-    }
-
-    public class CounterException extends Exception {
-        private static final long serialVersionUID = 2219781500857866035L;
-    }
-
-    /**
-     *  maximum levels of hierarchy
-     *  Example of moduleName/counterHierarchy:
-     *           switch/00:00:00:00:01:02:03:04/pktin/drops where
-     *           moduleName ==> "switch"  and
-     *           counterHierarchy of 3 ==> "00:00:00:00:01:02:03:04/pktin/drops"
-     */
-    public static final int MAX_HIERARCHY = 3;
-
-    /**
-     * All modules that wish to have the DebugCounterService count for them, must
-     * register their counters by making this call (typically from that module's
-     * 'startUp' method). The counter can then be updated, displayed, reset etc.
-     * using the registered moduleName and counterHierarchy.
-     *
-     * @param moduleName           the name of the module which is registering the
-     *                             counter eg. linkdiscovery or controller or switch
-     * @param counterHierarchy     the hierarchical counter name specifying all
-     *                             the hierarchical levels that come above it.
-     *                             For example: to register a drop counter for
-     *                             packet-ins from a switch, the counterHierarchy
-     *                             can be "00:00:00:00:01:02:03:04/pktin/drops"
-     *                             It is necessary that counters in hierarchical levels
-     *                             above have already been pre-registered - in this
-     *                             example: "00:00:00:00:01:02:03:04/pktin" and
-     *                             "00:00:00:00:01:02:03:04"
-     * @param counterDescription   a descriptive string that gives more information
-     *                             of what the counter is measuring. For example,
-     *                             "Measures the number of incoming packets seen by
-     *                             this module".
-     * @param counterType          One of CounterType. On-demand counter types
-     *                             need to be explicitly enabled/disabled using other
-     *                             methods in this API -- i.e. registering them is
-     *                             not enough to start counting.
-     * @param metaData             variable arguments that qualify a counter
-     *                             eg. warn, error etc.
-     * @return                     IDebugCounter with update methods that can be
-     *                             used to update a counter.
-     * @throws MaxCountersRegistered
-     * @throws MaxHierarchyRegistered
-     * @throws MissingHierarchicalLevel
-     */
-    public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
-                             String counterDescription, CounterType counterType,
-                             String... metaData)
-                throws MaxCountersRegistered, MaxHierarchyRegistered,
-                       MissingHierarchicalLevel;
-
-    /**
-     * Flush all thread-local counter values (from the current thread)
-     * to the global counter store. This method is not intended for use by any
-     * module. It's typical usage is from floodlight core and it is meant
-     * to flush those counters that are updated in the packet-processing pipeline,
-     * typically with the 'updateCounterNoFlush" methods in IDebugCounter.
-     */
-    public void flushCounters();
-
-    /**
-     * Resets the value of counters in the hierarchy to zero. Note that the reset
-     * applies to the level of counter hierarchy specified AND ALL LEVELS BELOW it
-     * in the hierarchy.
-     * For example: If a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops"
-     *              specifying a reset hierarchy: "00:00:00:00:01:02:03:04"
-     *              will reset all counters for the switch dpid specified;
-     *              while specifying a reset hierarchy: ""00:00:00:00:01:02:03:04/pktin"
-     *              will reset the pktin counter and all levels below it (like drops)
-     *              for the switch dpid specified.
-     */
-    void resetCounterHierarchy(String moduleName, String counterHierarchy);
-
-    /**
-     * Resets the values of all counters in the system.
-     */
-    public void resetAllCounters();
-
-    /**
-     * Resets the values of all counters belonging
-     * to a module with the given 'moduleName'.
-     */
-    public void resetAllModuleCounters(String moduleName);
-
-    /**
-     * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
-     * enable counting on the counter. Note that this step is necessary to start
-     * counting for these counter types - merely registering the counter is not
-     * enough (as is the case for CounterType.ALWAYS_COUNT). Newly
-     * enabled counters start from an initial value of zero.
-     *
-     * Enabling a counter in a counterHierarchy enables only THAT counter. It
-     * does not enable any other part of the counterHierarchy. For example, if
-     * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the
-     * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then enabling
-     * the 'pktin' counter by specifying the counterHierarchy as
-     * "00:00:00:00:01:02:03:04/pktin" does NOT enable the 'drops' counter.
-     */
-    public void enableCtrOnDemand(String moduleName, String counterHierarchy);
-
-    /**
-     * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
-     * enable counting on the counter. Note that disabling a counter results in a loss
-     * of the counter value. When re-enabled the counter will restart from zero.
-     *
-     * Disabling a counter in a counterHierarchy disables only THAT counter. It
-     * does not disable any other part of the counterHierarchy. For example, if
-     * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the
-     * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then disabling
-     * the 'pktin' counter by specifying the counterHierarchy as
-     * "00:00:00:00:01:02:03:04/pktin" does NOT disable the 'drops' counter.
-     */
-    public void disableCtrOnDemand(String moduleName, String counterHierarchy);
-
-    /**
-     * Get counter value and associated information for the specified counterHierarchy.
-     * Note that information on the level of counter hierarchy specified
-     * AND ALL LEVELS BELOW it in the hierarchy will be returned.
-     *
-     * For example,
-     * if a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", then
-     * specifying a counterHierarchy of "00:00:00:00:01:02:03:04/pktin" in the
-     * get call will return information on the 'pktin' as well as the 'drops'
-     * counters for the switch dpid specified.
-     *
-     * @return A list of DebugCounterInfo or an empty list if the counter
-     *         could not be found
-     */
-    public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
-                                                      String counterHierarchy);
-
-    /**
-     * Get counter values and associated information for all counters in the
-     * system
-     *
-     * @return the list of values/info or an empty list
-     */
-    public  List<DebugCounterInfo> getAllCounterValues();
-
-    /**
-     * Get counter values and associated information for all counters associated
-     * with a module.
-     *
-     * @param moduleName
-     * @return the list of values/info or an empty list
-     */
-    public  List<DebugCounterInfo> getModuleCounterValues(String moduleName);
-
-    /**
-     * Convenience method to figure out if the the given 'counterHierarchy' corresponds
-     * to a registered counterHierarchy for 'moduleName'. Note that the counter may or
-     * may not be enabled for counting, but if it is registered the method will
-     * return true.
-     *
-     * @param param
-     * @return false if moduleCounterHierarchy is not a registered counter
-     */
-    public boolean containsModuleCounterHierarchy(String moduleName,
-                                                  String counterHierarchy);
-
-    /**
-     * Convenience method to figure out if the the given 'moduleName' corresponds
-     * to a registered moduleName or not. Note that the module may or may not have
-     * a counter enabled for counting, but if it is registered the method will
-     * return true.
-     *
-     * @param param
-     * @return false if moduleName is not a registered counter
-     */
-    public boolean containsModuleName(String moduleName);
-
-    /**
-     * Returns a list of moduleNames registered for debug counters or an empty
-     * list if no counters have been registered in the system
-     */
-    public List<String> getModuleList();
-
-    /**
-     * Returns a list of all counters registered for a specific moduleName
-     * or a empty list
-     */
-    public List<String> getModuleCounterList(String moduleName);
-
-
-}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/MockDebugCounterService.java b/src/main/java/net/floodlightcontroller/debugcounter/MockDebugCounterService.java
new file mode 100644
index 000000000..354051963
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugcounter/MockDebugCounterService.java
@@ -0,0 +1,115 @@
+package net.floodlightcontroller.debugcounter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.projectfloodlight.core.module.FloodlightModuleContext;
+import org.projectfloodlight.core.module.FloodlightModuleException;
+import org.projectfloodlight.core.module.IFloodlightModule;
+import org.projectfloodlight.core.module.IFloodlightService;
+
+public class MockDebugCounterService implements IFloodlightModule, IDebugCounterService {
+
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleServices() {
+        Collection<Class<? extends IFloodlightService>> services =
+                new ArrayList<Class<? extends IFloodlightService>>(1);
+        services.add(IDebugCounterService.class);
+        return services;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService>
+            getServiceImpls() {
+        Map<Class<? extends IFloodlightService>,
+            IFloodlightService> m =
+                new HashMap<Class<? extends IFloodlightService>,
+                    IFloodlightService>();
+        m.put(IDebugCounterService.class, this);
+        return m;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleDependencies() {
+        return null;
+    }
+
+    @Override
+    public void init(FloodlightModuleContext context)
+            throws FloodlightModuleException {
+
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) {
+
+    }
+
+    @Override
+    public boolean registerModule(String moduleName) {
+        return true;
+    }
+
+    @Override
+    public IDebugCounter registerCounter(String moduleName,
+                                         String counterHierarchy,
+                                         String counterDescription,
+                                         MetaData... metaData) {
+        return new MockCounterImpl();
+    }
+
+    @Override
+    public boolean
+    resetCounterHierarchy(String moduleName, String counterHierarchy) {
+        return true;
+    }
+
+    @Override
+    public void resetAllCounters() {
+    }
+
+    @Override
+    public boolean resetAllModuleCounters(String moduleName) {
+        return true;
+    }
+
+    @Override
+    public List<DebugCounterResource>
+    getCounterHierarchy(String moduleName, String counterHierarchy) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<DebugCounterResource> getAllCounterValues() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<DebugCounterResource>
+    getModuleCounterValues(String moduleName) {
+        return Collections.emptyList();
+    }
+
+    public static class MockCounterImpl implements IDebugCounter {
+        @Override
+        public void increment() {
+        }
+
+        @Override
+        public void add(long incr) {
+        }
+
+        @Override
+        public long getCounterValue() {
+            return -1;
+        }
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java b/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java
deleted file mode 100644
index 5dc7b3192..000000000
--- a/src/main/java/net/floodlightcontroller/debugcounter/NullDebugCounter.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package net.floodlightcontroller.debugcounter;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-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.DebugCounter.DebugCounterInfo;
-
-public class NullDebugCounter implements IFloodlightModule, IDebugCounterService {
-
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> services =
-                new ArrayList<Class<? extends IFloodlightService>>(1);
-        services.add(IDebugCounterService.class);
-        return services;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        Map<Class<? extends IFloodlightService>,
-            IFloodlightService> m =
-                new HashMap<Class<? extends IFloodlightService>,
-                    IFloodlightService>();
-        m.put(IDebugCounterService.class, this);
-        return m;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleDependencies() {
-        return null;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)
-            throws FloodlightModuleException {
-
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-
-    }
-
-
-    @Override
-    public void flushCounters() {
-
-    }
-
-    @Override
-    public void resetAllCounters() {
-
-    }
-
-    @Override
-    public void resetAllModuleCounters(String moduleName) {
-
-    }
-
-
-    @Override
-    public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
-
-    }
-
-    @Override
-    public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
-
-    }
-
-    @Override
-    public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
-
-    }
-
-    @Override
-    public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
-                                                      String counterHierarchy) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<DebugCounterInfo> getAllCounterValues() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public boolean containsModuleCounterHierarchy(String moduleName,
-                                             String counterHierarchy) {
-        return false;
-    }
-
-    @Override
-    public boolean containsModuleName(String moduleName) {
-        return false;
-    }
-
-    @Override
-    public
-            IDebugCounter
-            registerCounter(String moduleName, String counterHierarchy,
-                            String counterDescription,
-                            CounterType counterType, String... metaData)
-                                 throws MaxCountersRegistered {
-        return new NullCounterImpl();
-    }
-
-    @Override
-    public List<String> getModuleList() {
-        return Collections.emptyList();
-    }
-
-    @Override
-    public List<String> getModuleCounterList(String moduleName) {
-        return Collections.emptyList();
-    }
-
-    public class NullCounterImpl implements IDebugCounter {
-
-        @Override
-        public void updateCounterWithFlush() {
-
-        }
-
-        @Override
-        public void updateCounterNoFlush() {
-
-        }
-
-        @Override
-        public void updateCounterWithFlush(int incr) {
-        }
-
-        @Override
-        public void updateCounterNoFlush(int incr) {
-
-        }
-
-        @Override
-        public long getCounterValue() {
-            return -1;
-        }
-
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/debugevent/DebugEventResource.java b/src/main/java/net/floodlightcontroller/debugevent/DebugEventResource.java
new file mode 100644
index 000000000..7e71d5490
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugevent/DebugEventResource.java
@@ -0,0 +1,207 @@
+package net.floodlightcontroller.debugevent;
+
+import java.util.List;
+
+import javax.annotation.concurrent.Immutable;
+
+import org.projectfloodlight.db.data.annotation.DBProperty;
+import org.projectfloodlight.debugevent.DebugEventService.EventInfo;
+import org.projectfloodlight.debugevent.IDebugEventService.EventType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * All the Immutable Resource classes for REST API.
+ */
+@Immutable
+public class DebugEventResource {
+
+    protected static final Logger logger = LoggerFactory.getLogger(DebugEventResource.class);
+    public static final String MODULE_NAME_PREDICATE = "module-name";
+    public static final String EVENT_NAME_PREDICATE = "event-name";
+    public static final String LAST_PREDICATE = "num-of-events";
+    public static final String EVENT_ID = "event-id";
+    public static final String EVENT_INSTANCE_ID = "event-instance-id";
+    public static final String ACKED = "acked";
+
+    /**
+     * Resource class for {@link EventInfo}. Used to create Immutable objects
+     * returned in response to REST calls.
+     */
+    @Immutable
+    public static class EventInfoResource implements
+        Comparable<EventInfoResource> {
+
+        private final int eventId;
+        private final boolean enabled;
+        private final int bufferCapacity;
+        private final EventType etype;
+        private final String eventDesc;
+        private final String eventName;
+        private final String moduleName;
+        private final int numOfEvents;
+        private final boolean ackable;
+        public final ImmutableList<EventResource> events;
+
+        public EventInfoResource(EventInfo eventInfo,
+                                 List<EventResource> events) {
+            super();
+            this.eventId = eventInfo.getEventId();
+            this.enabled = eventInfo.isEnabled();
+            this.bufferCapacity = eventInfo.getBufferCapacity();
+            this.etype = eventInfo.getEtype();
+            this.eventDesc = eventInfo.getEventDesc();
+            this.eventName = eventInfo.getEventName();
+            this.moduleName = eventInfo.getModuleName();
+            this.numOfEvents = eventInfo.getNumOfEvents();
+            this.ackable = eventInfo.isAckable();
+            this.events = ImmutableList.copyOf(events);
+        }
+
+        @DBProperty(value = "enabled")
+        public boolean isEnabled() {
+            return enabled;
+        }
+
+        @DBProperty(value = "buffer-capacity")
+        public int getBufferCapacity() {
+            return bufferCapacity;
+        }
+
+        @DBProperty(value = "etype")
+        public EventType getEtype() {
+            return etype;
+        }
+
+        @DBProperty(value = "event-desc")
+        public String getEventDesc() {
+            return eventDesc;
+        }
+
+        @DBProperty(value = "event-name")
+        public String getEventName() {
+            return eventName;
+        }
+
+        @DBProperty(value = "module-name")
+        public String getModuleName() {
+            return moduleName;
+        }
+
+        @DBProperty(value = "num-of-events")
+        public int getNumOfEvents() {
+            return numOfEvents;
+        }
+
+        @DBProperty(value = "ackable")
+        public boolean isAckable() {
+            return ackable;
+        }
+
+        @DBProperty(value = "event")
+        public List<EventResource> getEvents() {
+            return events;
+        }
+
+        @DBProperty(value = "event-id")
+        public int getEventId() {
+            return eventId;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + (ackable ? 1231 : 1237);
+            result = prime * result + bufferCapacity;
+            result = prime * result + (enabled ? 1231 : 1237);
+            result = prime * result
+                     + ((etype == null) ? 0 : etype.hashCode());
+            result = prime * result
+                     + ((eventDesc == null) ? 0 : eventDesc.hashCode());
+            result = prime * result + eventId;
+            result = prime * result
+                     + ((eventName == null) ? 0 : eventName.hashCode());
+            result = prime * result
+                     + ((events == null) ? 0 : events.hashCode());
+            result = prime * result
+                     + ((moduleName == null) ? 0 : moduleName.hashCode());
+            result = prime * result + numOfEvents;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null) return false;
+            if (getClass() != obj.getClass()) return false;
+            EventInfoResource other = (EventInfoResource) obj;
+            if (ackable != other.ackable) return false;
+            if (bufferCapacity != other.bufferCapacity) return false;
+            if (enabled != other.enabled) return false;
+            if (etype != other.etype) return false;
+            if (eventDesc == null) {
+                if (other.eventDesc != null) return false;
+            } else if (!eventDesc.equals(other.eventDesc)) return false;
+            if (eventId != other.eventId) return false;
+            if (eventName == null) {
+                if (other.eventName != null) return false;
+            } else if (!eventName.equals(other.eventName)) return false;
+            if (events == null) {
+                if (other.events != null) return false;
+            } else if (!events.equals(other.events)) return false;
+            if (moduleName == null) {
+                if (other.moduleName != null) return false;
+            } else if (!moduleName.equals(other.moduleName)) return false;
+            if (numOfEvents != other.numOfEvents) return false;
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("EventInfoResource [eventId=");
+            builder.append(eventId);
+            builder.append(", enabled=");
+            builder.append(enabled);
+            builder.append(", bufferCapacity=");
+            builder.append(bufferCapacity);
+            builder.append(", etype=");
+            builder.append(etype);
+            builder.append(", eventDesc=");
+            builder.append(eventDesc);
+            builder.append(", eventName=");
+            builder.append(eventName);
+            builder.append(", moduleName=");
+            builder.append(moduleName);
+            builder.append(", numOfEvents=");
+            builder.append(numOfEvents);
+            builder.append(", ackable=");
+            builder.append(ackable);
+            builder.append(", events=");
+            builder.append(events);
+            builder.append("]");
+            return builder.toString();
+        }
+
+        /**
+         * The natural order of this class is ascending on eventId and
+         * consistent with equals.
+         */
+        @Override
+        public int compareTo(EventInfoResource o) {
+            return ComparisonChain.start().compare(eventId, o.eventId)
+                                  .compareFalseFirst(enabled, o.enabled)
+                                  .compare(bufferCapacity, o.bufferCapacity)
+                                  .compare(etype, o.etype)
+                                  .compare(eventDesc, o.eventDesc)
+                                  .compare(eventName, o.eventName)
+                                  .compare(moduleName, o.moduleName)
+                                  .compare(numOfEvents, o.numOfEvents)
+                                  .result();
+        }
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/debugevent/DebugEventService.java b/src/main/java/net/floodlightcontroller/debugevent/DebugEventService.java
new file mode 100644
index 000000000..113a42002
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugevent/DebugEventService.java
@@ -0,0 +1,711 @@
+package net.floodlightcontroller.debugevent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.projectfloodlight.core.IShutdownListener;
+import org.projectfloodlight.core.IShutdownService;
+import org.projectfloodlight.core.module.FloodlightModuleContext;
+import org.projectfloodlight.core.module.IFloodlightModule;
+import org.projectfloodlight.core.module.IFloodlightService;
+import org.projectfloodlight.debugevent.DebugEventResource.EventInfoResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Sets;
+
+/**
+ * This class implements a central store for all events used for debugging the
+ * system. The basic idea is that given the functionality provided by this
+ * class, it should be unnecessary to resort to scraping through system
+ * DEBUG/TRACE logs to understand behavior in a running system.
+ *
+ * @author Saurav
+ */
+public class DebugEventService implements IFloodlightModule, IDebugEventService {
+    protected static final Logger log = LoggerFactory.getLogger(DebugEventService.class);
+
+    /**
+     * Every registered event type gets an event id AtomicInt to make the get
+     * operation thread-safe
+     */
+    private final AtomicInteger eventIdCounter = new AtomicInteger();
+
+    /**
+     * Unique Event Instance Id for ack-ing
+     */
+    private final AtomicLong eventInstanceId = new AtomicLong(Long.MAX_VALUE);
+
+    private static final int PCT_LOCAL_CAP = 10; // % of global capacity
+    private static final int MIN_LOCAL_CAPACITY = 10; // elements
+
+    /**
+     * EnumMap from {@link EventFieldType} to {@link CustomFormatter}
+     */
+    static final ImmutableMap<EventFieldType, CustomFormatter<?>> customFormatter =
+            new ImmutableMap.Builder<EventFieldType, CustomFormatter<?>>()
+            .put(EventFieldType.DPID, new CustomFormatterDpid())
+            .put(EventFieldType.IPv4, new CustomFormatterIpv4())
+              .put(EventFieldType.MAC, new CustomFormatterMac())
+              .put(EventFieldType.STRING, new CustomFormatterString())
+              .put(EventFieldType.OBJECT, new CustomFormatterObject())
+              .put(EventFieldType.PRIMITIVE, new CustomFormatterPrimitive())
+              .put(EventFieldType.COLLECTION_IPV4, new CustomFormatterCollectionIpv4())
+              .put(EventFieldType.COLLECTION_ATTACHMENT_POINT, new CustomFormatterCollectionAttachmentPoint())
+              .put(EventFieldType.COLLECTION_OBJECT, new CustomFormatterCollectionObject())
+              .put(EventFieldType.SREF_COLLECTION_OBJECT, new CustomFormatterSrefCollectionObject())
+              .put(EventFieldType.SREF_OBJECT, new CustomFormatterSrefObject())
+              .build();
+
+    /**
+     * Event Information
+     */
+    public static class EventInfo {
+        private final int eventId;
+        private final boolean enabled;
+        private final int bufferCapacity;
+        private int numOfEvents;
+        private final EventType etype;
+        private final String eventDesc;
+        private final String eventName;
+        private final String moduleName;
+        private final String moduleEventName;
+        private final Class<?> eventClass;
+        private final boolean ackable;
+
+        public EventInfo(int eventId, boolean enabled, boolean ackable,
+                         int bufferCapacity, EventType etype,
+                         Class<?> eventClass, String eventDesc,
+                         String eventName, String moduleName) {
+            this.enabled = enabled;
+            this.ackable = ackable;
+            this.eventId = eventId;
+            this.bufferCapacity = bufferCapacity;
+            this.numOfEvents = bufferCapacity;
+            this.etype = etype;
+            this.eventClass = eventClass;
+            this.eventDesc = eventDesc;
+            this.eventName = eventName;
+            this.moduleName = moduleName;
+            this.moduleEventName = moduleName + "/" + eventName;
+        }
+
+        public int getEventId() {
+            return eventId;
+        }
+
+        public boolean isEnabled() {
+            return enabled;
+        }
+
+        public boolean isAckable() {
+            return ackable;
+        }
+
+        public int getBufferCapacity() {
+            return bufferCapacity;
+        }
+
+        public int getNumOfEvents() {
+            return numOfEvents;
+        }
+
+        public EventType getEtype() {
+            return etype;
+        }
+
+        public String getEventDesc() {
+            return eventDesc;
+        }
+
+        public String getEventName() {
+            return eventName;
+        }
+
+        public String getModuleName() {
+            return moduleName;
+        }
+
+        public String getModuleEventName() {
+            return moduleEventName;
+        }
+    }
+
+    // ******************
+    // Global stores
+    // ******************
+
+    /**
+     * Event history for a particular event-id is stored in a circular buffer
+     */
+    protected static class DebugEventHistory {
+        EventInfo einfo;
+        LinkedBlockingDeque<Event> circularEventBuffer;
+
+        public DebugEventHistory(EventInfo einfo, int capacity) {
+            this.einfo = einfo;
+            this.circularEventBuffer = new LinkedBlockingDeque<Event>(
+                                                                      capacity);
+        }
+    }
+
+    /**
+     * Global storage for all event types and their corresponding event buffers.
+     * A particular event type is accessed by directly indexing into the Map
+     * with the corresponding event-id. <br/>
+     * It is a <b>Map</b> with <br/>
+     * <b>Key</b> Integer eventId <br/>
+     * <b>Value</b> DebugEventHistory
+     */
+    protected final ConcurrentHashMap<Integer, DebugEventHistory> allEvents = new ConcurrentHashMap<Integer, DebugEventHistory>();
+
+    /**
+     * Global storage for all event ids registered for a module. The map is
+     * indexed by the module name and event name and returns the event-ids that
+     * correspond to the event types registered by that module (for example
+     * module 'linkdiscovery' may register events that have ids 0 and 1 that
+     * correspond to link up/down events, and receiving malformed LLDP packets,
+     * respectively).
+     */
+    protected final ConcurrentHashMap<String, ConcurrentHashMap<String, Integer>> moduleEvents = new ConcurrentHashMap<String, ConcurrentHashMap<String, Integer>>();
+
+    /**
+     * A collection of event ids that are currently enabled for logging
+     */
+    protected final Set<Integer> currentEvents = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
+
+    // ******************
+    // Thread local stores
+    // ******************
+
+    /**
+     * Thread local storage for events
+     */
+    protected static class LocalEventHistory {
+        private boolean enabled;
+        private final int capacity;
+        private ArrayList<Event> eventList;
+
+        public LocalEventHistory(boolean enabled, int maxCapacity) {
+            this.enabled = enabled;
+            this.eventList = new ArrayList<Event>(maxCapacity);
+            this.capacity = maxCapacity;
+        }
+
+        public boolean add(Event e) {
+            if (this.eventList.size() < capacity) {
+                this.eventList.add(e);
+                return true;
+            }
+            return false;
+        }
+
+        public int drainTo(List<Event> eventList) {
+            int size = this.eventList.size();
+            Iterator<Event> iter = this.eventList.iterator();
+            while (iter.hasNext()) {
+                eventList.add(iter.next());
+            }
+            this.eventList.clear();
+            return size;
+        }
+
+        public boolean isFull() {
+            if (eventList.size() == capacity) return true;
+            return false;
+        }
+
+        public boolean isEmpty() {
+            return this.eventList.isEmpty();
+        }
+    }
+
+    /**
+     * Thread local event buffers used for maintaining event history local to a
+     * thread. Eventually this locally maintained information is flushed into
+     * the global event buffers. <br/>
+     * It is a <b>Map</b> with <br/>
+     * <b>Key</b> Integer eventId <br/>
+     * <b>Value</b> LocalEventHistory
+     */
+    protected final ThreadLocal<Map<Integer, LocalEventHistory>> threadlocalEvents = new ThreadLocal<Map<Integer, LocalEventHistory>>() {
+        @Override
+        protected Map<Integer, LocalEventHistory> initialValue() {
+            return new HashMap<Integer, LocalEventHistory>();
+        }
+    };
+
+    /**
+     * Thread local cache for event-ids that are currently active.
+     */
+    protected final ThreadLocal<Set<Integer>> threadlocalCurrentEvents = new ThreadLocal<Set<Integer>>() {
+        @Override
+        protected Set<Integer> initialValue() {
+            return new HashSet<Integer>();
+        }
+    };
+
+    // *******************************
+    // IEventCategory
+    // *******************************
+
+    protected class EventCategory<T> implements IEventCategory<T> {
+        private final int eventId;
+
+        public EventCategory(int evId) {
+            this.eventId = evId;
+        }
+
+        @Override
+        public void newEventNoFlush(Object event) {
+            if (!validEventId()) return;
+            newEvent(eventId, false, event);
+        }
+
+        @Override
+        public void newEventWithFlush(Object event) {
+            if (!validEventId()) return;
+            newEvent(eventId, true, event);
+        }
+
+        private boolean validEventId() {
+            if (eventId < 0) {
+                throw new IllegalStateException();
+            }
+            return true;
+        }
+    }
+
+    public class EventCategoryBuilder<T> {
+        private int eventId;
+        private String moduleName;
+        private String eventName;
+        private String eventDescription;
+        private EventType eventType;
+        private Class<T> eventClass;
+        private int bufferCapacity;
+        private boolean ackable;
+
+        public EventCategoryBuilder(Class<T> evClass) {
+            this.eventId = eventIdCounter.incrementAndGet();
+            this.eventClass = evClass;
+        }
+
+        public EventCategoryBuilder<T> setModuleName(String moduleName) {
+            this.moduleName = moduleName;
+            return this;
+        }
+
+        public EventCategoryBuilder<T> setEventName(String eventName) {
+            this.eventName = eventName;
+            return this;
+        }
+
+        public EventCategoryBuilder<T> setEventDescription(String eventDescription) {
+            this.eventDescription = eventDescription;
+            return this;
+        }
+
+        public EventCategoryBuilder<T> setEventType(EventType et) {
+            this.eventType = et;
+            return this;
+        }
+
+        public EventCategoryBuilder<T> setBufferCapacity(int bufferCapacity) {
+            this.bufferCapacity = bufferCapacity;
+            return this;
+        }
+
+        public EventCategoryBuilder<T> setAckable(boolean ackable) {
+            this.ackable = ackable;
+            return this;
+        }
+
+        /**
+         * Build a new {@link EventCategory<T>} <br/>
+         * Requires the following parameters to be set before being called:
+         *
+         * @param moduleName
+         *            module registering event eg. linkdiscovery, virtualrouting.
+         * @param eventName
+         *            name given to event.
+         * @param eventDescription
+         *            A descriptive string describing the event.
+         * @param eventType
+         *            EventType for this event. On-demand events have to be
+         *            explicitly enabled using other methods in this API
+         * @param eventClass
+         *            A user defined class that annotates the fields with
+         *            @EventColumn. This class specifies the fields/columns for this
+         *            event.
+         * @param bufferCapacity
+         *            Number of events to store for this event in a circular buffer.
+         *            Older events will be discarded once the buffer is full.
+         * @param ackable
+         *            is the event used as part of ackable-event framework boolean
+         *
+         * @return IEventCategory with <b>newEvent</b> method that can be used
+         * to create instances of event of the given eventClass
+         */
+        public EventCategory<T> register() {
+            // register event id for moduleName
+            moduleEvents.putIfAbsent(moduleName,
+                                     new ConcurrentHashMap<String, Integer>());
+            Integer eventExists = moduleEvents.get(moduleName)
+                                              .putIfAbsent(eventName, eventId);
+            if (eventExists != null) {
+                log.error("Duplicate event registration for moduleName {} eventName {}",
+                          moduleName, eventName);
+                return new EventCategory<T>(eventExists);
+            }
+
+            // create storage for event-type
+            boolean enabled = (eventType == EventType.ALWAYS_LOG) ? true : false;
+            EventInfo ei = new EventInfo(eventId, enabled, ackable,
+                                         bufferCapacity, eventType, eventClass,
+                                         eventDescription, eventName, moduleName);
+            allEvents.put(eventId, new DebugEventHistory(ei, bufferCapacity));
+            if (enabled) {
+                currentEvents.add(eventId);
+            }
+
+            return new EventCategory<T>(this.eventId);
+        }
+    }
+
+    // *******************************
+    // IDebugEventService
+    // *******************************
+
+    @Override
+    public <T> EventCategoryBuilder<T> buildEvent(Class<T> evClass) {
+        return new EventCategoryBuilder<T>(evClass);
+    }
+
+    private void flushLocalToGlobal(int eventId, LocalEventHistory le) {
+        DebugEventHistory de = allEvents.get(eventId);
+        if (de.einfo.enabled) {
+            List<Event> transferEvents = new ArrayList<Event>();
+            // drain local buffer to Collection
+            int size = le.drainTo(transferEvents);
+            // if global buffer doesn't have enough space, clear
+            // some space
+            int requiredSpace = size
+                                - de.circularEventBuffer.remainingCapacity();
+            if (requiredSpace > 0) {
+                for (int i = 0; i < requiredSpace; i++) {
+                    de.circularEventBuffer.removeFirst();
+                }
+            }
+            de.circularEventBuffer.addAll(transferEvents);
+        } else {
+            le.enabled = false;
+            this.threadlocalCurrentEvents.get().remove(eventId);
+        }
+    }
+
+    private void newEvent(int eventId, boolean flushNow, Object eventData) {
+        if (eventId < 0) {
+            throw new IllegalStateException("Invalid eventId");
+        }
+
+        Map<Integer, LocalEventHistory> thishist = this.threadlocalEvents.get();
+        if (!thishist.containsKey(eventId)) {
+            // seeing this event for the first time in this thread - create
+            // local
+            // store by consulting global store
+            if (allEvents.containsKey(eventId)) {
+                DebugEventHistory de = allEvents.get(eventId);
+                boolean enabled = de.einfo.enabled;
+                int localCapacity = de.einfo.bufferCapacity * PCT_LOCAL_CAP
+                                    / 100;
+                if (localCapacity < 10) localCapacity = MIN_LOCAL_CAPACITY;
+                thishist.put(eventId, new LocalEventHistory(enabled,
+                                                            localCapacity));
+                if (enabled) {
+                    Set<Integer> thisset = this.threadlocalCurrentEvents.get();
+                    thisset.add(eventId);
+                }
+            } else {
+                log.error("updateEvent seen locally for event {} but no global"
+                                  + "storage exists for it yet .. not updating",
+                          eventId);
+                return;
+            }
+        }
+
+        // update local store if enabled locally for updating
+        LocalEventHistory le = thishist.get(eventId);
+        if (le.enabled) {
+            try {
+                le.add(new Event(System.currentTimeMillis(),
+                                 Thread.currentThread().getId(),
+                                 Thread.currentThread().getName(),
+                                 eventData,
+                                 /*
+                                  * the eventInstanceId is started in reverse
+                                  * order so BigDB gets the values in ascending
+                                  * order Initialization in startUp()
+                                  */
+                                 eventInstanceId.decrementAndGet()));
+
+                if (le.isFull() || flushNow) {
+                    flushLocalToGlobal(eventId, le);
+                }
+            } catch (IllegalStateException ise) {
+                log.debug("Exception while adding event locally: "
+                          + ise.getMessage());
+            }
+        }
+    }
+
+    @Override
+    public void flushEvents() {
+        Map<Integer, LocalEventHistory> thishist = this.threadlocalEvents.get();
+        Set<Integer> thisset = this.threadlocalCurrentEvents.get();
+
+        for (int eventId : thisset) {
+            if (thishist.containsKey(eventId)) {
+                LocalEventHistory le = thishist.get(eventId);
+                if (!le.isEmpty()) {
+                    flushLocalToGlobal(eventId, le);
+                }
+            }
+        }
+
+        // sync thread local currently enabled set of eventIds with global set.
+        Sets.SetView<Integer> sv = Sets.difference(currentEvents, thisset);
+        for (int eventId : sv) {
+            if (thishist.containsKey(eventId)) {
+                thishist.get(eventId).enabled = true;
+                thisset.add(eventId);
+            }
+        }
+
+    }
+
+    @Override
+    public boolean containsModuleEventName(String moduleName,
+                                           String eventName) {
+        if (!moduleEvents.containsKey(moduleName)) return false;
+        if (moduleEvents.get(moduleName).containsKey(eventName))
+                                                                return true;
+        return false;
+    }
+
+    @Override
+    public boolean containsModuleName(String moduleName) {
+        return moduleEvents.containsKey(moduleName);
+    }
+
+    @Override
+    public List<EventInfoResource> getAllEventHistory() {
+        List<EventInfoResource> moduleEventList = new ArrayList<EventInfoResource>();
+        for (Map<String, Integer> modev : moduleEvents.values()) {
+            for (int eventId : modev.values()) {
+                if (allEvents.containsKey(eventId)) {
+                    DebugEventHistory de = allEvents.get(eventId);
+
+                    List<EventResource> eventData = new ArrayList<EventResource>();
+                    // take snapshot and iterate
+                    Iterator<Event> iter = de.circularEventBuffer.descendingIterator();
+                    while (iter.hasNext()) {
+                        Event e = iter.next();
+                        eventData.add(e.getFormattedEvent(de.einfo.eventClass,
+                                                          de.einfo.moduleEventName));
+                    }
+                    moduleEventList.add(new EventInfoResource(de.einfo,
+                                                              eventData));
+                }
+            }
+        }
+        traceLogDebugHistory(moduleEventList);
+        return moduleEventList;
+    }
+
+    @Override
+    public List<EventInfoResource> getModuleEventHistory(String moduleName) {
+        if (!moduleEvents.containsKey(moduleName))
+                                                  return Collections.emptyList();
+        List<EventInfoResource> moduleEventList = new ArrayList<EventInfoResource>();
+        for (int eventId : moduleEvents.get(moduleName).values()) {
+            if (allEvents.containsKey(eventId)) {
+                DebugEventHistory de = allEvents.get(eventId);
+
+                List<EventResource> eventData = new ArrayList<EventResource>();
+                // take snapshot and iterate
+                Iterator<Event> iter = de.circularEventBuffer.descendingIterator();
+                while (iter.hasNext()) {
+                    Event e = iter.next();
+                    eventData.add(e.getFormattedEvent(de.einfo.eventClass,
+                                                      de.einfo.moduleEventName));
+                }
+                moduleEventList.add(new EventInfoResource(de.einfo,
+                                                          eventData));
+            }
+        }
+        traceLogDebugHistory(moduleEventList);
+        return moduleEventList;
+    }
+
+    @Override
+    public EventInfoResource getSingleEventHistory(String moduleName,
+                                                   String eventName,
+                                                   int numOfEvents) {
+        if (!moduleEvents.containsKey(moduleName)) return null;
+        Integer eventId = moduleEvents.get(moduleName).get(eventName);
+        if (eventId == null) return null;
+
+        if (!allEvents.containsKey(eventId)) return null;
+
+        DebugEventHistory de = allEvents.get(eventId);
+        if (numOfEvents == 0) numOfEvents = de.einfo.bufferCapacity;
+
+        de.einfo.numOfEvents = numOfEvents;
+        int num = 1;
+        List<EventResource> eventData = new ArrayList<EventResource>();
+        // take snapshot and iterate
+        Iterator<Event> iter = de.circularEventBuffer.descendingIterator();
+        while (iter.hasNext()) {
+            Event e = iter.next();
+            if (num > numOfEvents) break;
+            eventData.add(e.getFormattedEvent(de.einfo.eventClass,
+                                              de.einfo.moduleEventName));
+            num++;
+        }
+        EventInfoResource ret = new EventInfoResource(de.einfo, eventData);
+        traceLogDebugHistory(Collections.singletonList(ret));
+        return ret;
+    }
+
+    @Override
+    public void resetAllEvents() {
+        for (Map<String, Integer> eventMap : moduleEvents.values()) {
+            for (Integer evId : eventMap.values()) {
+                allEvents.get(evId).circularEventBuffer.clear();
+            }
+        }
+    }
+
+    @Override
+    public void resetAllModuleEvents(String moduleName) {
+        if (!moduleEvents.containsKey(moduleName)) return;
+        Map<String, Integer> modEvents = moduleEvents.get(moduleName);
+        for (Integer evId : modEvents.values()) {
+            allEvents.get(evId).circularEventBuffer.clear();
+        }
+    }
+
+    @Override
+    public void resetSingleEvent(String moduleName, String eventName) {
+        if (!moduleEvents.containsKey(moduleName)) return;
+        Integer eventId = moduleEvents.get(moduleName).get(eventName);
+        if (eventId == null) return;
+
+        if (allEvents.containsKey(eventId)) {
+            allEvents.get(eventId).circularEventBuffer.clear();
+        }
+    }
+
+    @Override
+    public void setAck(int eventId, long eventInstanceId, boolean ack) {
+        if (allEvents.containsKey(eventId)) {
+            for (Event e : allEvents.get(eventId).circularEventBuffer) {
+                if (e.getEventInstanceId() == eventInstanceId) {
+                    e.setAcked(ack);
+                }
+            }
+        }
+    }
+
+    @Override
+    public List<String> getModuleList() {
+        List<String> el = new ArrayList<String>();
+        el.addAll(moduleEvents.keySet());
+        return el;
+    }
+
+    @Override
+    public List<String> getModuleEventList(String moduleName) {
+        if (!moduleEvents.containsKey(moduleName))
+                                                  return Collections.emptyList();
+        List<String> el = new ArrayList<String>();
+        el.addAll(moduleEvents.get(moduleName).keySet());
+        return el;
+    }
+
+
+    private void traceLogDebugHistory(List<EventInfoResource> l) {
+        if (!log.isTraceEnabled()) {
+            return;
+        }
+        for (EventInfoResource eir: l) {
+            for (EventResource der: eir.getEvents()) {
+                log.trace("{}", der);
+            }
+        }
+    }
+
+    private class ShutdownListenenerDelegate implements IShutdownListener {
+        @Override
+        public void floodlightIsShuttingDown() {
+            for (EventInfoResource eir: getAllEventHistory()) {
+                for (EventResource der: eir.getEvents()) {
+                    log.info("{}", der);
+                }
+            }
+        }
+    }
+
+    // *******************************
+    // IFloodlightModule
+    // *******************************
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleServices() {
+        Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
+        l.add(IDebugEventService.class);
+        return l;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService>
+            getServiceImpls() {
+        Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+        m.put(IDebugEventService.class, this);
+        return m;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleDependencies() {
+        ArrayList<Class<? extends IFloodlightService>> deps = new ArrayList<Class<? extends IFloodlightService>>();
+        deps.add(IShutdownService.class);
+        return deps;
+    }
+
+    @Override
+    public void init(FloodlightModuleContext context) {
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) {
+        IShutdownService shutdownService =
+                context.getServiceImpl(IShutdownService.class);
+        shutdownService.registerShutdownListener(new ShutdownListenenerDelegate());
+        DebugEventAppender.setDebugEventServiceImpl(this);
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/debugevent/Event.java b/src/main/java/net/floodlightcontroller/debugevent/Event.java
index 3e0ac6db3..1eb76a1a8 100644
--- a/src/main/java/net/floodlightcontroller/debugevent/Event.java
+++ b/src/main/java/net/floodlightcontroller/debugevent/Event.java
@@ -11,8 +11,10 @@ import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
 import net.floodlightcontroller.devicemanager.SwitchPort;
 import net.floodlightcontroller.packet.IPv4;
 
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
+import org.projectfloodlight.openflow.protocol.OFFlowModify;
+import org.projectfloodlight.openflow.util.HexString;
 
 public class Event {
     long timestamp;
@@ -110,8 +112,8 @@ public class Event {
                         if (flags == 0) {
                             builder.append("None");
                         }
-                        else {
-                            if ((flags & OFFlowMod.OFPFF_SEND_FLOW_REM) != 0) {
+                        else { //towirevalue
+                            if ((flags & OFFlowModFlags.SEND_FLOW_REM.) != 0) {
                                 builder.append("SEND_FLOW_REM ");
                             }
                             if ((flags & OFFlowMod.OFPFF_CHECK_OVERLAP) != 0) {
diff --git a/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java b/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java
deleted file mode 100644
index d54e9f632..000000000
--- a/src/main/java/net/floodlightcontroller/debugevent/IDebugEventService.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package net.floodlightcontroller.debugevent;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.util.List;
-import java.util.Map;
-
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.debugevent.DebugEvent.EventInfo;
-
-public interface IDebugEventService extends IFloodlightService {
-
-    /**
-     * Different event types. Events that are meant to be logged on demand
-     * need to be separately enabled/disabled.
-     */
-    public enum EventType {
-        ALWAYS_LOG,
-        LOG_ON_DEMAND
-    }
-
-    /**
-     * Describes the type of field obtained from reflection
-     */
-    enum EventFieldType {
-        DPID, IPv4, MAC, STRING, OBJECT, PRIMITIVE, LIST_IPV4,
-        LIST_ATTACHMENT_POINT, LIST_OBJECT, SREF_LIST_OBJECT, SREF_OBJECT,
-        FLOW_MOD_FLAGS
-    }
-
-    /**
-     * EventColumn is the only annotation given to the fields of the event
-     * when updating an event.
-     */
-    @Target(ElementType.FIELD)
-    @Retention(RetentionPolicy.RUNTIME)
-    public @interface EventColumn {
-        String name() default "param";
-        EventFieldType description() default EventFieldType.PRIMITIVE;
-    }
-
-    /**
-     * Debug Event Qualifiers
-     */
-    public static final String EV_MDATA_WARN = "warn";
-    public static final String EV_MDATA_ERROR = "error";
-
-    /**
-     *  A limit on the maximum number of events that can be created
-     */
-    public static final int MAX_EVENTS = 2000;
-
-    /**
-     * Public class for information returned in response to rest API calls.
-     */
-    public class DebugEventInfo {
-        EventInfo eventInfo;
-        List<Map<String,String>> events;
-
-        public DebugEventInfo(EventInfo eventInfo,
-                              List<Map<String, String>> eventHistory) {
-            this.eventInfo = eventInfo;
-            this.events = eventHistory;
-        }
-
-        public EventInfo getEventInfo() {
-            return eventInfo;
-        }
-
-        public List<Map<String,String>> getEvents() {
-            return events;
-        }
-    }
-
-    /**
-    * exception thrown when MAX_EVENTS have been registered
-    */
-    public class MaxEventsRegistered extends Exception {
-        private static final long serialVersionUID = 2609587082227510262L;
-    }
-
-    /**
-     * Register an event for debugging.
-     *
-     * @param moduleName       module registering event eg. linkdiscovery, virtualrouting.
-     * @param eventName        name given to event.
-     * @param eventDescription A descriptive string describing the event.
-     * @param eventType        EventType for this event. On-demand events have to
-     *                         be explicitly enabled using other methods in this API
-     * @param eventClass       A user defined class that annotates the fields
-     *                         with @EventColumn. This class specifies the
-     *                         fields/columns for this event.
-     * @param bufferCapacity   Number of events to store for this event in a circular
-     *                         buffer. Older events will be discarded once the
-     *                         buffer is full.
-     * @param metaData         variable arguments that qualify an event
-     *                         eg. EV_MDATA_WARN, EV_MDATA_ERROR etc. See Debug Event Qualifiers
-     * @return                 IEventUpdater with update methods that can be used to
-     *                         update an event of the given eventClass
-     * @throws MaxEventsRegistered
-     */
-    public <T> IEventUpdater<T> registerEvent(String moduleName, String eventName,
-                                              String eventDescription,
-                                              EventType eventType,
-                                              Class<T> eventClass,
-                                              int bufferCapacity,
-                                              String... metaData)
-                                                      throws MaxEventsRegistered;
-
-    /**
-     * Update the global event stores with values from the thread local stores. This
-     * method is not typically intended for use by any module. It's typical usage is from
-     * floodlight core for events that happen in the packet processing pipeline.
-     * For other rare events, flushEvents should be called.
-     */
-    public void flushEvents();
-
-    /**
-     * Determine if eventName is a registered event for a given moduleName
-     */
-    public boolean containsModuleEventName(String moduleName, String eventName);
-
-    /**
-     * Determine if any events have been registered for module of name moduleName
-     */
-    public boolean containsModuleName(String moduleName);
-
-    /**
-     * Get event history for all events. This call can be expensive as it
-     * formats the event histories for all events.
-     *
-     * @return  a list of all event histories or an empty list if no events have
-     *          been registered
-     */
-    public List<DebugEventInfo> getAllEventHistory();
-
-    /**
-     * Get event history for all events registered for a given moduleName
-     *
-     * @return  a list of all event histories for all events registered for the
-     *          the module or an empty list if there are no events for this module
-     */
-    public List<DebugEventInfo> getModuleEventHistory(String moduleName);
-
-    /**
-     * Get event history for a single event
-     *
-     * @param  moduleName  registered module name
-     * @param  eventName   registered event name for moduleName
-     * @param  last        last X events
-     * @return DebugEventInfo for that event, or null if the moduleEventName
-     *         does not correspond to a registered event.
-     */
-    public DebugEventInfo getSingleEventHistory(String moduleName, String eventName, int last);
-
-    /**
-     * Wipe out all event history for all registered events
-     */
-    public void resetAllEvents();
-
-    /**
-     * Wipe out all event history for all events registered for a specific module
-     *
-     * @param moduleName  registered module name
-     */
-    public void resetAllModuleEvents(String moduleName);
-
-    /**
-     * Wipe out event history for a single event
-     * @param  moduleName  registered module name
-     * @param  eventName   registered event name for moduleName
-     */
-    public void resetSingleEvent(String moduleName, String eventName);
-
-    /**
-     * Retrieve a list of moduleNames registered for debug events or an empty
-     * list if no events have been registered in the system
-     */
-    public List<String> getModuleList();
-
-    /**
-     * Returns a list of all events registered for a specific moduleName
-     * or a empty list
-     */
-    public List<String> getModuleEventList(String moduleName);
-
-}
diff --git a/src/main/java/net/floodlightcontroller/debugevent/IEventCategory.java b/src/main/java/net/floodlightcontroller/debugevent/IEventCategory.java
new file mode 100644
index 000000000..00cea1232
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugevent/IEventCategory.java
@@ -0,0 +1,30 @@
+package net.floodlightcontroller.debugevent;
+
+/**
+ * EventCategory is used to log events for pre-registered events.
+ */
+public interface IEventCategory<T> {
+
+    /**
+     * Logs the instance of the event thread-locally. Flushing to the global
+     * circular buffer for this event is delayed resulting in better
+     * performance. This method should typically be used by those events that
+     * happen in the packet processing pipeline
+     *
+     * @param event
+     *            an instance of the user-defined event of type T
+     */
+    public void newEventNoFlush(T event);
+
+    /**
+     * Logs the instance of the event thread-locally and immediated flushes to
+     * the global circular buffer for this event. This method should typically
+     * be used by those events that happen outside the packet processing
+     * pipeline
+     *
+     * @param event
+     *            an instance of the user-defined event of type T
+     */
+    public void newEventWithFlush(T event);
+
+}
diff --git a/src/main/java/net/floodlightcontroller/debugevent/MockDebugEventService.java b/src/main/java/net/floodlightcontroller/debugevent/MockDebugEventService.java
new file mode 100644
index 000000000..7f0676a55
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/debugevent/MockDebugEventService.java
@@ -0,0 +1,128 @@
+package net.floodlightcontroller.debugevent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.debugevent.DebugEventResource.EventInfoResource;
+import net.floodlightcontroller.debugevent.DebugEventService.EventCategoryBuilder;
+
+public class MockDebugEventService implements IFloodlightModule, IDebugEventService {
+
+    @Override
+    public <T> EventCategoryBuilder<T> buildEvent(Class<T> evClass) {
+        DebugEventService des = new DebugEventService();
+        return des.buildEvent(evClass);
+    }
+
+    @Override
+    public void flushEvents() {
+
+    }
+
+    @Override
+    public boolean containsModuleEventName(String moduleName,
+                                           String eventName) {
+        return false;
+    }
+
+    @Override
+    public boolean containsModuleName(String moduleName) {
+        return false;
+    }
+
+    @Override
+    public List<EventInfoResource> getAllEventHistory() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<EventInfoResource> getModuleEventHistory(String moduleName) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public EventInfoResource getSingleEventHistory(String moduleName,
+                                                   String eventName,
+                                                   int numOfEvents) {
+        return null;
+    }
+
+    @Override
+    public void resetAllEvents() {
+
+    }
+
+    @Override
+    public void resetAllModuleEvents(String moduleName) {
+
+    }
+
+    @Override
+    public void resetSingleEvent(String moduleName, String eventName) {
+
+    }
+
+    @Override
+    public List<String> getModuleList() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<String> getModuleEventList(String moduleName) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void setAck(int eventId, long eventInstanceId, boolean ack) {
+
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleServices() {
+        Collection<Class<? extends IFloodlightService>> services =
+                new ArrayList<Class<? extends IFloodlightService>>(1);
+        services.add(IDebugEventService.class);
+        return services;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService>
+            getServiceImpls() {
+        Map<Class<? extends IFloodlightService>, IFloodlightService> m =
+                new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+        m.put(IDebugEventService.class, this);
+        return m;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>>
+            getModuleDependencies() {
+        return null;
+    }
+
+    @Override
+    public
+            void
+            init(FloodlightModuleContext context)
+                                                 throws FloodlightModuleException {
+
+    }
+
+    @Override
+    public
+            void
+            startUp(FloodlightModuleContext context)
+                                                    throws FloodlightModuleException {
+
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDevice.java b/src/main/java/net/floodlightcontroller/devicemanager/IDevice.java
index 4593b7bac..4d5ba9be6 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/IDevice.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/IDevice.java
@@ -19,6 +19,10 @@ package net.floodlightcontroller.devicemanager;
 
 import java.util.Date;
 
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.VlanVid;
+
 
 /**
  * Represents an independent device on the network.  A device consists of a 
@@ -37,7 +41,7 @@ public interface IDevice {
      * Get the MAC address of the device as a Long value.
      * @return the MAC address for the device
      */
-    public long getMACAddress();
+    public MacAddress getMACAddress();
 
     /**
      * Get the MAC address of the device as a String value.
@@ -50,13 +54,13 @@ public interface IDevice {
      * entities, then the value -1 will be returned.
      * @return an array containing all unique VLAN IDs for the device.
      */
-    public Short[] getVlanId();
+    public VlanVid[] getVlanId();
     
     /**
      * Get all unique IPv4 addresses associated with the device.
      * @return an array containing the unique IPv4 addresses for the device.
      */
-    public Integer[] getIPv4Addresses();
+    public IPv4Address[] getIPv4Addresses();
     
     /**
      * Get all unique attachment points associated with the device.  This will
@@ -85,7 +89,7 @@ public interface IDevice {
      * @param swp the switch port to query
      * @return an array containing the unique VLAN IDs
      */
-    public Short[] getSwitchPortVlanIds(SwitchPort swp);
+    public VlanVid[] getSwitchPortVlanIds(SwitchPort swp);
     
     /**
      * Get the most recent timestamp for this device
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java
index eb3801344..40d729f68 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/IDeviceService.java
@@ -22,6 +22,12 @@ import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.Set;
 
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.VlanVid;
+import org.projectfloodlight.openflow.types.OFPort;
+
 import net.floodlightcontroller.core.FloodlightContextStore;
 import net.floodlightcontroller.core.module.IFloodlightService;
 
@@ -95,9 +101,9 @@ public interface IDeviceService extends IFloodlightService {
      * @throws IllegalArgumentException if not all key fields of the
      * current {@link IEntityClassifierService} are specified.
      */
-    public IDevice findDevice(long macAddress, Short vlan,
-                              Integer ipv4Address, Long switchDPID,
-                              Integer switchPort)
+    public IDevice findDevice(MacAddress macAddress, VlanVid vlan,
+                              IPv4Address ipv4Address, DatapathId switchDPID,
+                              OFPort switchPort)
                               throws IllegalArgumentException;
     
     /**
@@ -122,8 +128,8 @@ public interface IDeviceService extends IFloodlightService {
      * source's {@link IEntityClass} are specified.
      */
     public IDevice findClassDevice(IEntityClass entityClass,
-                                   long macAddress, Short vlan,
-                                   Integer ipv4Address)
+                                   MacAddress macAddress, VlanVid vlan,
+                                   IPv4Address ipv4Address)
                                    throws IllegalArgumentException;
 
     /**
@@ -162,11 +168,11 @@ public interface IDeviceService extends IFloodlightService {
      * @see IDeviceService#queryClassDevices(IEntityClass, Long, 
      * Short, Integer, Long, Integer)
      */
-    public Iterator<? extends IDevice> queryDevices(Long macAddress,
-                                                    Short vlan,
-                                                    Integer ipv4Address, 
-                                                    Long switchDPID,
-                                                    Integer switchPort);
+    public Iterator<? extends IDevice> queryDevices(MacAddress macAddress,
+                                                    VlanVid vlan,
+                                                    IPv4Address ipv4Address, 
+                                                    DatapathId switchDPID,
+                                                    OFPort switchPort);
 
     /**
      * Find devices that match the provided query.  Only the index for
@@ -187,11 +193,11 @@ public interface IDeviceService extends IFloodlightService {
      * Short, Integer, Long, Integer)
      */
     public Iterator<? extends IDevice> queryClassDevices(IEntityClass entityClass,
-                                                         Long macAddress,
-                                                         Short vlan,
-                                                         Integer ipv4Address, 
-                                                         Long switchDPID,
-                                                         Integer switchPort);
+                                                         MacAddress macAddress,
+                                                         VlanVid vlan,
+                                                         IPv4Address ipv4Address, 
+                                                         DatapathId switchDPID,
+                                                         OFPort switchPort);
     
     /**
      * Adds a listener to listen for IDeviceManagerServices notifications
@@ -207,9 +213,9 @@ public interface IDeviceService extends IFloodlightService {
      * @param sw
      * @param port
      */
-    public void addSuppressAPs(long swId, short port);
+    public void addSuppressAPs(DatapathId swId, OFPort port);
 
-    public void removeSuppressAPs(long swId, short port);
+    public void removeSuppressAPs(DatapathId swId, OFPort port);
 
     public Set<SwitchPort> getSuppressAPs();
 
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/SwitchPort.java b/src/main/java/net/floodlightcontroller/devicemanager/SwitchPort.java
index 9fe62d950..d057f9c4a 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/SwitchPort.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/SwitchPort.java
@@ -17,7 +17,8 @@
 
 package net.floodlightcontroller.devicemanager;
 
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
 
 import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
 
@@ -55,8 +56,8 @@ public class SwitchPort {
         }
     }
 
-    private final long switchDPID;
-    private final int port;
+    private final DatapathId switchDPID;
+    private final OFPort port;
     private final ErrorStatus errorStatus;
 
     /**
@@ -65,7 +66,7 @@ public class SwitchPort {
      * @param port the port
      * @param errorStatus any error status for the switch port
      */
-    public SwitchPort(long switchDPID, int port, ErrorStatus errorStatus) {
+    public SwitchPort(DatapathId switchDPID, OFPort port, ErrorStatus errorStatus) {
         super();
         this.switchDPID = switchDPID;
         this.port = port;
@@ -77,7 +78,7 @@ public class SwitchPort {
      * @param switchDPID the dpid
      * @param port the port
      */
-    public SwitchPort(long switchDPID, int port) {
+    public SwitchPort(DatapathId switchDPID, OFPort port) {
         super();
         this.switchDPID = switchDPID;
         this.port = port;
@@ -89,11 +90,11 @@ public class SwitchPort {
     // ***************
 
     @JsonSerialize(using=DPIDSerializer.class)
-    public long getSwitchDPID() {
+    public DatapathId getSwitchDPID() {
         return switchDPID;
     }
 
-    public int getPort() {
+    public OFPort getPort() {
         return port;
     }
 
@@ -113,8 +114,8 @@ public class SwitchPort {
                         + ((errorStatus == null)
                                 ? 0
                                 : errorStatus.hashCode());
-        result = prime * result + port;
-        result = prime * result + (int) (switchDPID ^ (switchDPID >>> 32));
+        result = prime * result + port.getPortNumber();
+        result = prime * result + (int) (switchDPID.getLong() ^ (switchDPID.getLong() >>> 32));
         return result;
     }
 
@@ -132,7 +133,7 @@ public class SwitchPort {
 
     @Override
     public String toString() {
-        return "SwitchPort [switchDPID=" + HexString.toHexString(switchDPID) +
+        return "SwitchPort [switchDPID=" + switchDPID.toString() +
                ", port=" + port + ", errorStatus=" + errorStatus + "]";
     }
 
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/AttachmentPoint.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/AttachmentPoint.java
index a08a3a5d2..46c2408fa 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/AttachmentPoint.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/AttachmentPoint.java
@@ -21,11 +21,16 @@
 
 package net.floodlightcontroller.devicemanager.internal;
 
+import java.util.Date;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+
 public class AttachmentPoint {
-    long  sw;
-    short port;
-    long  activeSince;
-    long  lastSeen;
+    DatapathId  sw;
+    OFPort port;
+    Date  activeSince;
+    Date  lastSeen;
 
     // Timeout for moving attachment points from OF/broadcast
     // domain to another.
@@ -34,15 +39,15 @@ public class AttachmentPoint {
     public static final long OPENFLOW_TO_EXTERNAL_TIMEOUT = 30000; // 30 seconds
     public static final long CONSISTENT_TIMEOUT = 30000;           // 30 seconds
 
-    public AttachmentPoint(long sw, short port, long activeSince,
-                           long lastSeen) {
+    public AttachmentPoint(DatapathId sw, OFPort port, Date activeSince,
+                           Date lastSeen) {
         this.sw = sw;
         this.port = port;
         this.activeSince = activeSince;
         this.lastSeen = lastSeen;
     }
 
-    public AttachmentPoint(long sw, short port, long lastSeen) {
+    public AttachmentPoint(DatapathId sw, OFPort port, Date lastSeen) {
         this.sw = sw;
         this.port = port;
         this.lastSeen = lastSeen;
@@ -56,31 +61,31 @@ public class AttachmentPoint {
         this.lastSeen = ap.lastSeen;
     }
 
-    public long getSw() {
+    public DatapathId getSw() {
         return sw;
     }
-    public void setSw(long sw) {
+    public void setSw(DatapathId sw) {
         this.sw = sw;
     }
-    public short getPort() {
+    public OFPort getPort() {
         return port;
     }
-    public void setPort(short port) {
+    public void setPort(OFPort port) {
         this.port = port;
     }
-    public long getActiveSince() {
+    public Date getActiveSince() {
         return activeSince;
     }
-    public void setActiveSince(long activeSince) {
+    public void setActiveSince(Date activeSince) {
         this.activeSince = activeSince;
     }
-    public long getLastSeen() {
+    public Date getLastSeen() {
         return lastSeen;
     }
-    public void setLastSeen(long lastSeen) {
-        if (this.lastSeen + INACTIVITY_INTERVAL < lastSeen)
+    public void setLastSeen(Date lastSeen) {
+        if (this.lastSeen.getTime() + INACTIVITY_INTERVAL < lastSeen.getTime())
             this.activeSince = lastSeen;
-        if (this.lastSeen < lastSeen)
+        if (this.lastSeen.before(lastSeen))
             this.lastSeen = lastSeen;
     }
 
@@ -91,8 +96,8 @@ public class AttachmentPoint {
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + port;
-        result = prime * result + (int) (sw ^ (sw >>> 32));
+        result = prime * result + port.getPortNumber();
+        result = prime * result + (int) (sw.getLong() ^ (sw.getLong() >>> 32));
         return result;
     }
 
@@ -118,7 +123,7 @@ public class AttachmentPoint {
     @Override
     public String toString() {
         return "AttachmentPoint [sw=" + sw + ", port=" + port
-               + ", activeSince=" + activeSince + ", lastSeen=" + lastSeen
+               + ", activeSince=" + activeSince + ", lastSeen=" + lastSeen.toString()
                + "]";
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
index ef0ba3468..07e5b77bf 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
@@ -30,7 +30,11 @@ import java.util.Map;
 import java.util.TreeSet;
 
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.openflow.util.HexString;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.VlanVid;
+import org.projectfloodlight.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -61,7 +65,7 @@ public class Device implements IDevice {
 
     protected final String macAddressString;
     // the vlan Ids from the entities of this device
-    protected final Short[] vlanIds;
+    protected final VlanVid[] vlanIds;
     protected volatile String dhcpClientName;
 
     /**
@@ -103,7 +107,7 @@ public class Device implements IDevice {
 
         if (entity.getSwitchDPID() != null &&
                 entity.getSwitchPort() != null){
-            long sw = entity.getSwitchDPID();
+            DatapathId sw = entity.getSwitchDPID();
             short port = entity.getSwitchPort().shortValue();
 
             if (deviceManager.isValidAttachmentPoint(sw, port)) {
@@ -209,30 +213,29 @@ public class Device implements IDevice {
                     new ArrayList<AttachmentPoint>(device.attachmentPoints);
         }
 
-        this.macAddressString =
-                HexString.toHexString(this.entities[0].getMacAddress(), 6);
+        this.macAddressString = this.entities[0].getMacAddress().toString();
 
         this.entityClass = device.entityClass;
         vlanIds = computeVlandIds();
     }
 
-    private Short[]  computeVlandIds() {
+    private VlanVid[] computeVlandIds() {
         if (entities.length == 1) {
             if (entities[0].getVlan() != null) {
-                return new Short[]{ entities[0].getVlan() };
+                return new VlanVid[]{ entities[0].getVlan() };
             } else {
-                return new Short[] { Short.valueOf((short)-1) };
+                return new VlanVid[] { VlanVid.ofVlan(-1) };
             }
         }
 
-        TreeSet<Short> vals = new TreeSet<Short>();
+        TreeSet<VlanVid> vals = new TreeSet<VlanVid>();
         for (Entity e : entities) {
             if (e.getVlan() == null)
-                vals.add((short)-1);
+                vals.add(VlanVid.ofVlan(-1));
             else
                 vals.add(e.getVlan());
         }
-        return vals.toArray(new Short[vals.size()]);
+        return vals.toArray(new VlanVid[vals.size()]);
     }
 
     /**
@@ -293,7 +296,7 @@ public class Device implements IDevice {
         if (apList == null) return false;
 
         for(AttachmentPoint ap: apList) {
-            if (ap.getLastSeen() + AttachmentPoint.INACTIVITY_INTERVAL <
+            if (ap.getLastSeen().getTime() + AttachmentPoint.INACTIVITY_INTERVAL <
                     System.currentTimeMillis())
                 expiredAPs.add(ap);
         }
@@ -332,8 +335,8 @@ public class Device implements IDevice {
             if (trueAP == null) continue;
             boolean c = (topology.isConsistent(trueAP.getSw(), trueAP.getPort(),
                                               ap.getSw(), ap.getPort()));
-            boolean active = (ap.getActiveSince() > trueAP.getActiveSince());
-            boolean last = ap.getLastSeen() > timeThreshold;
+            boolean active = (ap.getActiveSince().after(trueAP.getActiveSince()));
+            boolean last = ap.getLastSeen().getTime() > timeThreshold;
             if (!c && active && last) {
                 dupAPs.add(ap);
             }
@@ -385,7 +388,7 @@ public class Device implements IDevice {
      * @param lastSeen
      * @return
      */
-    protected boolean updateAttachmentPoint(long sw, short port, long lastSeen){
+    protected boolean updateAttachmentPoint(DatapathId sw, OFPort port, Date lastSeen){
         ITopologyService topology = deviceManager.topology;
         List<AttachmentPoint> oldAPList;
         List<AttachmentPoint> apList;
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java
index 2cbea66e5..d9a7a4532 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceIterator.java
@@ -20,6 +20,12 @@ package net.floodlightcontroller.devicemanager.internal;
 import java.util.Arrays;
 import java.util.Iterator;
 
+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.IEntityClass;
 import net.floodlightcontroller.devicemanager.SwitchPort;
 import net.floodlightcontroller.util.FilterIterator;
@@ -30,11 +36,11 @@ import net.floodlightcontroller.util.FilterIterator;
 public class DeviceIterator extends FilterIterator<Device> {
     private IEntityClass[] entityClasses;
     
-    private Long macAddress;
-    private Short vlan;
-    private Integer ipv4Address; 
-    private Long switchDPID;
-    private Integer switchPort;
+    private MacAddress macAddress;
+    private VlanVid vlan;
+    private IPv4Address ipv4Address; 
+    private DatapathId switchDPID;
+    private OFPort switchPort;
     
     /**
      * Construct a new device iterator over the key fields
@@ -48,11 +54,11 @@ public class DeviceIterator extends FilterIterator<Device> {
      */
     public DeviceIterator(Iterator<Device> subIterator, 
                           IEntityClass[] entityClasses,
-                          Long macAddress,
-                          Short vlan, 
-                          Integer ipv4Address, 
-                          Long switchDPID,
-                          Integer switchPort) {
+                          MacAddress macAddress,
+                          VlanVid vlan, 
+                          IPv4Address ipv4Address, 
+                          DatapathId switchDPID,
+                          OFPort switchPort) {
         super(subIterator);
         this.entityClasses = entityClasses;
         this.subIterator = subIterator;
@@ -80,7 +86,7 @@ public class DeviceIterator extends FilterIterator<Device> {
             if (!match) return false;                
         }
         if (macAddress != null) {
-            if (macAddress.longValue() != value.getMACAddress())
+            if (macAddress.getLong() != value.getMACAddress())
                 return false;
         }
         if (vlan != null) {
@@ -100,11 +106,11 @@ public class DeviceIterator extends FilterIterator<Device> {
             match = false;
             for (SwitchPort sp : sps) {
                 if (switchDPID != null) {
-                    if (switchDPID.longValue() != sp.getSwitchDPID())
+                    if (switchDPID.getLong() != sp.getSwitchDPID().getLong())
                         return false;
                 }
                 if (switchPort != null) {
-                    if (switchPort.intValue() != sp.getPort())
+                    if (switchPort.getPortNumber() != sp.getPort().getPortNumber())
                         return false;
                 }
                 match = true;
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index e4f67420b..7d34fc3f6 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -47,7 +47,7 @@ import net.floodlightcontroller.core.IHAListener;
 import net.floodlightcontroller.core.IInfoProvider;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.core.HARole;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
@@ -96,11 +96,15 @@ import net.floodlightcontroller.util.MultiIterator;
 import static net.floodlightcontroller.devicemanager.internal.
 DeviceManagerImpl.DeviceUpdate.Change.*;
 
-import org.openflow.protocol.OFMatchWithSwDpid;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFMatchWithSwDpid;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+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.projectfloodlight.openflow.protocol.OFType;
 import org.sdnplatform.sync.IClosableIterator;
 import org.sdnplatform.sync.IStoreClient;
 import org.sdnplatform.sync.ISyncService;
@@ -360,33 +364,33 @@ IFlowReconcileListener, IInfoProvider {
         public int compare(AttachmentPoint oldAP, AttachmentPoint newAP) {
             //First compare based on L2 domain ID;
 
-            long oldSw = oldAP.getSw();
-            short oldPort = oldAP.getPort();
-            long oldDomain = topology.getL2DomainId(oldSw);
+            DatapathId oldSw = oldAP.getSw();
+            OFPort oldPort = oldAP.getPort();
+            DatapathId oldDomain = topology.getL2DomainId(oldSw);
             boolean oldBD = topology.isBroadcastDomainPort(oldSw, oldPort);
 
-            long newSw = newAP.getSw();
-            short newPort = newAP.getPort();
-            long newDomain = topology.getL2DomainId(newSw);
+            DatapathId newSw = newAP.getSw();
+            OFPort newPort = newAP.getPort();
+            DatapathId newDomain = topology.getL2DomainId(newSw);
             boolean newBD = topology.isBroadcastDomainPort(newSw, newPort);
 
-            if (oldDomain < newDomain) return -1;
-            else if (oldDomain > newDomain) return 1;
+            if (oldDomain.getLong() < newDomain.getLong()) return -1;
+            else if (oldDomain.getLong() > newDomain.getLong()) return 1;
 
 
-            // Give preference to OFPP_LOCAL always
-            if (oldPort != OFPort.OFPP_LOCAL.getValue() &&
-                    newPort == OFPort.OFPP_LOCAL.getValue()) {
+            // Give preference to LOCAL always
+            if (oldPort != OFPort.LOCAL &&
+                    newPort == OFPort.LOCAL) {
                 return -1;
-            } else if (oldPort == OFPort.OFPP_LOCAL.getValue() &&
-                    newPort != OFPort.OFPP_LOCAL.getValue()) {
+            } else if (oldPort == OFPort.LOCAL &&
+                    newPort != OFPort.LOCAL) {
                 return 1;
             }
 
             // We expect that the last seen of the new AP is higher than
             // old AP, if it is not, just reverse and send the negative
             // of the result.
-            if (oldAP.getActiveSince() > newAP.getActiveSince())
+            if (oldAP.getActiveSince().after(newAP.getActiveSince()))
                 return -compare(newAP, oldAP);
 
             long activeOffset = 0;
@@ -407,8 +411,8 @@ IFlowReconcileListener, IInfoProvider {
             }
 
 
-            if ((newAP.getActiveSince() > oldAP.getLastSeen() + activeOffset) ||
-                    (newAP.getLastSeen() > oldAP.getLastSeen() +
+            if ((newAP.getActiveSince().getTime() > oldAP.getLastSeen().getTime() + activeOffset) ||
+                    (newAP.getLastSeen().getTime() > oldAP.getLastSeen().getTime() +
                             AttachmentPoint.INACTIVITY_INTERVAL)) {
                 return -1;
             }
@@ -453,13 +457,13 @@ IFlowReconcileListener, IInfoProvider {
     }
 
     @Override
-    public IDevice findDevice(long macAddress, Short vlan,
-                              Integer ipv4Address, Long switchDPID,
-                              Integer switchPort)
+    public IDevice findDevice(MacAddress macAddress, VlanVid vlan,
+                              IPv4Address ipv4Address, DatapathId switchDPID,
+                              OFPort switchPort)
                               throws IllegalArgumentException {
-        if (vlan != null && vlan.shortValue() <= 0)
+        if (vlan != null && vlan.getVlan() <= 0)
             vlan = null;
-        if (ipv4Address != null && ipv4Address == 0)
+        if (ipv4Address != null && ipv4Address.getInt() == 0)
             ipv4Address = null;
         Entity e = new Entity(macAddress, vlan, ipv4Address, switchDPID,
                               switchPort, null);
@@ -471,12 +475,12 @@ IFlowReconcileListener, IInfoProvider {
     }
 
     @Override
-    public IDevice findClassDevice(IEntityClass entityClass, long macAddress,
-                                  Short vlan, Integer ipv4Address)
+    public IDevice findClassDevice(IEntityClass entityClass, MacAddress macAddress,
+                                  VlanVid vlan, IPv4Address ipv4Address)
                                   throws IllegalArgumentException {
-        if (vlan != null && vlan.shortValue() <= 0)
+        if (vlan != null && vlan.getVlan() <= 0)
             vlan = null;
-        if (ipv4Address != null && ipv4Address == 0)
+        if (ipv4Address != null && ipv4Address.getInt() == 0)
             ipv4Address = null;
         Entity e = new Entity(macAddress, vlan, ipv4Address,
                               null, null, null);
@@ -506,11 +510,11 @@ IFlowReconcileListener, IInfoProvider {
     }
 
     @Override
-    public Iterator<? extends IDevice> queryDevices(Long macAddress,
-                                                    Short vlan,
-                                                    Integer ipv4Address,
-                                                    Long switchDPID,
-                                                    Integer switchPort) {
+    public Iterator<? extends IDevice> queryDevices(MacAddress macAddress,
+                                                    VlanVid vlan,
+                                                    IPv4Address ipv4Address,
+                                                    DatapathId switchDPID,
+                                                    OFPort switchPort) {
         DeviceIndex index = null;
         if (secondaryIndexMap.size() > 0) {
             EnumSet<DeviceField> keys =
@@ -525,7 +529,7 @@ IFlowReconcileListener, IInfoProvider {
             deviceIterator = deviceMap.values().iterator();
         } else {
             // index lookup
-            Entity entity = new Entity((macAddress == null ? 0 : macAddress),
+            Entity entity = new Entity(macAddress,
                                        vlan,
                                        ipv4Address,
                                        switchDPID,
@@ -548,11 +552,11 @@ IFlowReconcileListener, IInfoProvider {
 
     @Override
     public Iterator<? extends IDevice> queryClassDevices(IEntityClass entityClass,
-                                                         Long macAddress,
-                                                         Short vlan,
-                                                         Integer ipv4Address,
-                                                         Long switchDPID,
-                                                         Integer switchPort) {
+                                                         MacAddress macAddress,
+                                                         VlanVid vlan,
+                                                         IPv4Address ipv4Address,
+                                                         DatapathId switchDPID,
+                                                         OFPort switchPort) {
         ArrayList<Iterator<Device>> iterators =
                 new ArrayList<Iterator<Device>>();
         ClassState classState = getClassState(entityClass);
@@ -581,7 +585,7 @@ IFlowReconcileListener, IInfoProvider {
         } else {
             // index lookup
             Entity entity =
-                    new Entity((macAddress == null ? 0 : macAddress),
+                    new Entity(macAddress,
                                vlan,
                                ipv4Address,
                                switchDPID,
@@ -595,11 +599,11 @@ IFlowReconcileListener, IInfoProvider {
         return new MultiIterator<Device>(iterators.iterator());
     }
 
-    protected Iterator<Device> getDeviceIteratorForQuery(Long macAddress,
-                                                        Short vlan,
-                                                        Integer ipv4Address,
-                                                        Long switchDPID,
-                                                        Integer switchPort) {
+    protected Iterator<Device> getDeviceIteratorForQuery(MacAddress macAddress,
+                                                        VlanVid vlan,
+                                                        IPv4Address ipv4Address,
+                                                        DatapathId switchDPID,
+                                                        OFPort switchPort) {
         DeviceIndex index = null;
         if (secondaryIndexMap.size() > 0) {
             EnumSet<DeviceField> keys =
@@ -614,7 +618,7 @@ IFlowReconcileListener, IInfoProvider {
             deviceIterator = deviceMap.values().iterator();
         } else {
             // index lookup
-            Entity entity = new Entity((macAddress == null ? 0 : macAddress),
+            Entity entity = new Entity(macAddress,
                                 vlan,
                                 ipv4Address,
                                 switchDPID,
@@ -642,12 +646,12 @@ IFlowReconcileListener, IInfoProvider {
     }
 
     @Override
-    public void addSuppressAPs(long swId, short port) {
+    public void addSuppressAPs(DatapathId swId, OFPort port) {
         suppressAPs.add(new SwitchPort(swId, port));
     }
 
     @Override
-    public void removeSuppressAPs(long swId, short port) {
+    public void removeSuppressAPs(DatapathId swId, OFPort port) {
         suppressAPs.remove(new SwitchPort(swId, port));
     }
 
@@ -714,14 +718,14 @@ IFlowReconcileListener, IInfoProvider {
         }
 
         private void generateDeviceEvent(IDevice device, String reason) {
-            List<Integer> ipv4Addresses =
-                new ArrayList<Integer>(Arrays.asList(device.getIPv4Addresses()));
+            List<IPv4Address> ipv4Addresses =
+                new ArrayList<IPv4Address>(Arrays.asList(device.getIPv4Addresses()));
             List<SwitchPort> oldAps =
                 new ArrayList<SwitchPort>(Arrays.asList(device.getOldAP()));
             List<SwitchPort> currentAps =
                     new ArrayList<SwitchPort>(Arrays.asList(device.getAttachmentPoints()));
-            List<Short> vlanIds =
-                    new ArrayList<Short>(Arrays.asList(device.getVlanId()));
+            List<VlanVid> vlanIds =
+                    new ArrayList<VlanVid>(Arrays.asList(device.getVlanId()));
 
             evDevice.updateEventNoFlush(
                     new DeviceEvent(device.getMACAddress(),
@@ -771,7 +775,7 @@ IFlowReconcileListener, IInfoProvider {
                            FloodlightContext cntx) {
         switch (msg.getType()) {
             case PACKET_IN:
-                cntIncoming.updateCounterNoFlush();
+                cntIncoming.increment();
                 return this.processPacketInMessage(sw,
                                                    (OFPacketIn) msg, cntx);
             default:
@@ -803,19 +807,19 @@ IFlowReconcileListener, IInfoProvider {
     }
 
     protected Command reconcileFlow(OFMatchReconcile ofm) {
-        cntReconcileRequest.updateCounterNoFlush();
+        cntReconcileRequest.increment();
         // Extract source entity information
         Entity srcEntity =
                 getEntityFromFlowMod(ofm.ofmWithSwDpid, true);
         if (srcEntity == null) {
-            cntReconcileNoSource.updateCounterNoFlush();
+            cntReconcileNoSource.increment();
             return Command.STOP;
        }
 
         // Find the device by source entity
         Device srcDevice = findDeviceByEntity(srcEntity);
         if (srcDevice == null)  {
-            cntReconcileNoSource.updateCounterNoFlush();
+            cntReconcileNoSource.increment();
             return Command.STOP;
         }
         // Store the source device in the context
@@ -830,9 +834,9 @@ IFlowReconcileListener, IInfoProvider {
             if (dstDevice != null)
                 fcStore.put(ofm.cntx, CONTEXT_DST_DEVICE, dstDevice);
             else
-                cntReconcileNoDest.updateCounterNoFlush();
+                cntReconcileNoDest.increment();
         } else {
-            cntReconcileNoDest.updateCounterNoFlush();
+            cntReconcileNoDest.increment();
         }
         if (logger.isTraceEnabled()) {
             logger.trace("Reconciling flow: match={}, srcEntity={}, srcDev={}, "
@@ -1189,7 +1193,7 @@ IFlowReconcileListener, IInfoProvider {
         Entity srcEntity =
                 getSourceEntityFromPacket(eth, sw.getId(), pi.getInPort());
         if (srcEntity == null) {
-            cntInvalidSource.updateCounterNoFlush();
+            cntInvalidSource.increment();
             return Command.STOP;
         }
 
@@ -1204,7 +1208,7 @@ IFlowReconcileListener, IInfoProvider {
         // Learn/lookup device information
         Device srcDevice = learnDeviceByEntity(srcEntity);
         if (srcDevice == null) {
-            cntNoSource.updateCounterNoFlush();
+            cntNoSource.increment();
             return Command.STOP;
         }
 
@@ -1214,7 +1218,7 @@ IFlowReconcileListener, IInfoProvider {
         // Find the device matching the destination from the entity
         // classes of the source.
         if (eth.getDestinationMAC().toLong() == 0) {
-            cntInvalidDest.updateCounterNoFlush();
+            cntInvalidDest.increment();
             return Command.STOP;
         }
         Entity dstEntity = getDestEntityFromPacket(eth);
@@ -1225,9 +1229,9 @@ IFlowReconcileListener, IInfoProvider {
             if (dstDevice != null)
                 fcStore.put(cntx, CONTEXT_DST_DEVICE, dstDevice);
             else
-                cntNoDest.updateCounterNoFlush();
+                cntNoDest.increment();
         } else {
-            cntNoDest.updateCounterNoFlush();
+            cntNoDest.increment();
         }
 
        if (logger.isTraceEnabled()) {
@@ -1262,7 +1266,7 @@ IFlowReconcileListener, IInfoProvider {
             DHCPOption dhcpOption = dhcp.getOption(
                     DHCPOptionCode.OptionCode_Hostname);
             if (dhcpOption != null) {
-                cntDhcpClientNameSnooped.updateCounterNoFlush();
+                cntDhcpClientNameSnooped.increment();
                 srcDevice.dhcpClientName = new String(dhcpOption.getData());
             }
         }
@@ -1314,23 +1318,22 @@ IFlowReconcileListener, IInfoProvider {
      * @return the entity from the packet
      */
     protected Entity getSourceEntityFromPacket(Ethernet eth,
-                                             long swdpid,
-                                             int port) {
-        byte[] dlAddrArr = eth.getSourceMACAddress();
-        long dlAddr = Ethernet.toLong(dlAddrArr);
-
+                                             DatapathId swdpid,
+                                             OFPort port) {
+        MacAddress dlAddr = MacAddress.of(eth.getSourceMACAddress());
+        
         // Ignore broadcast/multicast source
-        if ((dlAddrArr[0] & 0x1) != 0)
+        if (dlAddr.isBroadcast() || dlAddr.isMulticast())
             return null;
         // Ignore 0 source mac
-        if (dlAddr == 0)
+        if (dlAddr.getLong() == 0)
             return null;
 
-        short vlan = eth.getVlanID();
-        int nwSrc = getSrcNwAddr(eth, dlAddr);
+        VlanVid vlan = VlanVid.ofVlan(eth.getVlanID());
+        IPv4Address nwSrc = getSrcNwAddr(eth, dlAddr);
         return new Entity(dlAddr,
-                          ((vlan >= 0) ? vlan : null),
-                          ((nwSrc != 0) ? nwSrc : null),
+                          vlan,
+                          nwSrc,
                           swdpid,
                           port,
                           new Date());
@@ -1342,8 +1345,8 @@ IFlowReconcileListener, IInfoProvider {
      * address in ARP data.
      */
     protected void learnDeviceFromArpResponseData(Ethernet eth,
-                                            long swdpid,
-                                            int port) {
+                                            DatapathId swdpid,
+                                            OFPort port) {
 
         if (!(eth.getPayload() instanceof ARP)) return;
         ARP arp = (ARP) eth.getPayload();
@@ -1612,8 +1615,8 @@ IFlowReconcileListener, IInfoProvider {
                 // attachment point port. Otherwise ignore.
                 if (entity.hasSwitchPort() &&
                         !topology.isAttachmentPointPort(entity.getSwitchDPID(),
-                                                 entity.getSwitchPort().shortValue())) {
-                    cntDeviceOnInternalPortNotLearned.updateCounterNoFlush();
+                                                 entity.getSwitchPort())) {
+                    cntDeviceOnInternalPortNotLearned.increment();
                     if (logger.isDebugEnabled()) {
                         logger.debug("Not learning new device on internal"
                                      + " link: {}", entity);
@@ -1624,7 +1627,7 @@ IFlowReconcileListener, IInfoProvider {
                 // Before we create the new device also check if
                 // the entity is allowed (e.g., for spoofing protection)
                 if (!isEntityAllowed(entity, entityClass)) {
-                    cntPacketNotAllowed.updateCounterNoFlush();
+                    cntPacketNotAllowed.increment();
                     if (logger.isDebugEnabled()) {
                         logger.debug("PacketIn is not allowed {} {}",
                                     entityClass.getName(), entity);
@@ -1652,7 +1655,7 @@ IFlowReconcileListener, IInfoProvider {
                 // We need to count and log here. If we log earlier we could
                 // hit a concurrent modification and restart the dev creation
                 // and potentially count the device twice.
-                cntNewDevice.updateCounterNoFlush();
+                cntNewDevice.increment();
                 if (logger.isDebugEnabled()) {
                     logger.debug("New device created: {} deviceKey={}, entity={}",
                                  new Object[]{device, deviceKey, entity});
@@ -1666,7 +1669,7 @@ IFlowReconcileListener, IInfoProvider {
             }
             // if it gets here, we have a pre-existing Device for this Entity
             if (!isEntityAllowed(entity, device.getEntityClass())) {
-                cntPacketNotAllowed.updateCounterNoFlush();
+                cntPacketNotAllowed.increment();
                 if (logger.isDebugEnabled()) {
                     logger.info("PacketIn is not allowed {} {}",
                                 device.getEntityClass().getName(), entity);
@@ -1678,8 +1681,8 @@ IFlowReconcileListener, IInfoProvider {
             // the chain.
             if (entity.hasSwitchPort() &&
                     !topology.isAttachmentPointPort(entity.getSwitchDPID(),
-                                                 entity.getSwitchPort().shortValue())) {
-                cntPacketOnInternalPortForKnownDevice.updateCounterNoFlush();
+                                                 entity.getSwitchPort())) {
+                cntPacketOnInternalPortForKnownDevice.increment();
                 break;
             }
             int entityindex = -1;
@@ -1723,9 +1726,9 @@ IFlowReconcileListener, IInfoProvider {
 
                 // We need to count here after all the possible "continue"
                 // statements in this branch
-                cntNewEntity.updateCounterNoFlush();
+                cntNewEntity.increment();
                 if (changedFields.size() > 0) {
-                    cntDeviceChanged.updateCounterNoFlush();
+                    cntDeviceChanged.increment();
                     deviceUpdates =
                     updateUpdates(deviceUpdates,
                                   new DeviceUpdate(newDevice, CHANGE,
@@ -1738,8 +1741,8 @@ IFlowReconcileListener, IInfoProvider {
             if (entity.hasSwitchPort()) {
                 boolean moved =
                         device.updateAttachmentPoint(entity.getSwitchDPID(),
-                                entity.getSwitchPort().shortValue(),
-                                entity.getLastSeenTimestamp().getTime());
+                                entity.getSwitchPort(),
+                                entity.getLastSeenTimestamp());
                 // TODO: use update mechanism instead of sending the
                 // notification directly
                 if (moved) {
@@ -1986,7 +1989,7 @@ IFlowReconcileListener, IInfoProvider {
      * Clean up expired entities/devices
      */
     protected void cleanupEntities () {
-        cntCleanupEntitiesRuns.updateCounterWithFlush();
+        cntCleanupEntitiesRuns.increment();
 
         Calendar c = Calendar.getInstance();
         c.add(Calendar.MILLISECOND, -ENTITY_TIMEOUT);
@@ -2019,7 +2022,7 @@ IFlowReconcileListener, IInfoProvider {
                     break;
                 }
 
-                cntEntityRemovedTimeout.updateCounterWithFlush();
+                cntEntityRemovedTimeout.increment();
                 for (Entity e : toRemove) {
                     removeEntity(e, d.getEntityClass(), d.getDeviceKey(), toKeep);
                 }
@@ -2055,7 +2058,7 @@ IFlowReconcileListener, IInfoProvider {
                     if (update != null) {
                         // need to count after all possibly continue stmts in
                         // this branch
-                        cntDeviceChanged.updateCounterWithFlush();
+                        cntDeviceChanged.increment();
                         deviceUpdates.add(update);
                     }
                 } else {
@@ -2067,7 +2070,7 @@ IFlowReconcileListener, IInfoProvider {
                         d = deviceMap.get(d.getDeviceKey());
                         if (null != d)
                             continue;
-                        cntDeviceDeleted.updateCounterWithFlush();
+                        cntDeviceDeleted.increment();
                     }
                     deviceUpdates.add(update);
                 }
@@ -2125,11 +2128,11 @@ IFlowReconcileListener, IInfoProvider {
         }
     }
 
-    private EnumSet<DeviceField> getEntityKeys(Long macAddress,
-                                               Short vlan,
-                                               Integer ipv4Address,
-                                               Long switchDPID,
-                                               Integer switchPort) {
+    private EnumSet<DeviceField> getEntityKeys(MacAddress macAddress,
+                                               VlanVid vlan,
+                                               IPv4Address ipv4Address,
+                                               DatapathId switchDPID,
+                                               OFPort switchPort) {
         // FIXME: vlan==null is a valid search. Need to handle this
         // case correctly. Note that the code will still work correctly.
         // But we might do a full device search instead of using an index.
@@ -2183,8 +2186,8 @@ IFlowReconcileListener, IInfoProvider {
         for (Entity entity : entities) {
             if (entity.switchDPID != null && entity.switchPort != null) {
                 AttachmentPoint aP =
-                        new AttachmentPoint(entity.switchDPID.longValue(),
-                                    entity.switchPort.shortValue(), 0);
+                        new AttachmentPoint(entity.switchDPID,
+                                    entity.switchPort, new Date(0));
                 newPossibleAPs.add(aP);
             }
         }
@@ -2241,7 +2244,7 @@ IFlowReconcileListener, IInfoProvider {
      * @param updates the updates to process.
      */
     protected void sendDeviceMovedNotification(Device d) {
-        cntDeviceMoved.updateCounterNoFlush();
+        cntDeviceMoved.increment();
         deviceSyncManager.storeDevice(d);
         List<IDeviceListener> listeners = deviceListeners.getOrderedListeners();
         if (listeners != null) {
@@ -2300,7 +2303,7 @@ IFlowReconcileListener, IInfoProvider {
             return false;
         }
 
-        cntDeviceReclassifyDelete.updateCounterNoFlush();
+        cntDeviceReclassifyDelete.increment();
         LinkedList<DeviceUpdate> deviceUpdates =
                 new LinkedList<DeviceUpdate>();
         // delete this device and then re-learn all the entities
@@ -2385,7 +2388,7 @@ IFlowReconcileListener, IInfoProvider {
                 writeUpdatedDeviceToStorage(d);
                 lastWriteTimes.put(d.getDeviceKey(), now);
             } else {
-                cntDeviceStoreThrottled.updateCounterWithFlush();
+                cntDeviceStoreThrottled.increment();
             }
         }
 
@@ -2406,12 +2409,12 @@ IFlowReconcileListener, IInfoProvider {
                 // TODO: should probably do versioned delete. OTOH, even
                 // if we accidentally delete, we'll write it again after
                 // the next entity ....
-                cntDeviceRemovedFromStore.updateCounterWithFlush();
+                cntDeviceRemovedFromStore.increment();
                 storeClient.delete(DeviceSyncRepresentation.computeKey(d));
             } catch(ObsoleteVersionException e) {
                 // FIXME
             } catch (SyncException e) {
-                cntSyncException.updateCounterWithFlush();
+                cntSyncException.increment();
                 logger.error("Could not remove device " + d + " from store", e);
             }
         }
@@ -2423,14 +2426,14 @@ IFlowReconcileListener, IInfoProvider {
          */
         private void removeDevice(Versioned<DeviceSyncRepresentation> dev) {
             try {
-                cntDeviceRemovedFromStore.updateCounterWithFlush();
+                cntDeviceRemovedFromStore.increment();
                 storeClient.delete(dev.getValue().getKey(),
                                    dev.getVersion());
             } catch(ObsoleteVersionException e) {
                 // Key was locally modified by another thread.
                 // Do not delete and ignore.
             } catch(SyncException e) {
-                cntSyncException.updateCounterWithFlush();
+                cntSyncException.increment();
                 logger.error("Failed to remove device entry for " +
                             dev.toString() + " from store.", e);
             }
@@ -2444,13 +2447,13 @@ IFlowReconcileListener, IInfoProvider {
             if (logger.isDebugEnabled()) {
                 logger.debug("Transitioning to MASTER role");
             }
-            cntTransitionToMaster.updateCounterWithFlush();
+            cntTransitionToMaster.increment();
             IClosableIterator<Map.Entry<String,Versioned<DeviceSyncRepresentation>>>
                     iter = null;
             try {
                 iter = storeClient.entries();
             } catch (SyncException e) {
-                cntSyncException.updateCounterWithFlush();
+                cntSyncException.increment();
                 logger.error("Failed to read devices from sync store", e);
                 return;
             }
@@ -2462,7 +2465,7 @@ IFlowReconcileListener, IInfoProvider {
                             versionedDevice.getValue();
                     if (storedDevice == null)
                         continue;
-                    cntDevicesFromStore.updateCounterWithFlush();
+                    cntDevicesFromStore.increment();
                     for(SyncEntity se: storedDevice.getEntities()) {
                         learnDeviceByEntity(se.asEntity());
                     }
@@ -2482,7 +2485,7 @@ IFlowReconcileListener, IInfoProvider {
          */
         private void writeUpdatedDeviceToStorage(Device device) {
             try {
-                cntDeviceStrored.updateCounterWithFlush();
+                cntDeviceStrored.increment();
                 // FIXME: use a versioned put
                 DeviceSyncRepresentation storeDevice =
                         new DeviceSyncRepresentation(device);
@@ -2491,7 +2494,7 @@ IFlowReconcileListener, IInfoProvider {
                 // FIXME: what's the right behavior here. Can the store client
                 // even throw this error?
             } catch (SyncException e) {
-                cntSyncException.updateCounterWithFlush();
+                cntSyncException.increment();
                 logger.error("Could not write device " + device +
                           " to sync store:", e);
             }
@@ -2515,7 +2518,7 @@ IFlowReconcileListener, IInfoProvider {
         private void consolidateStore() {
             if (!isMaster)
                 return;
-            cntConsolidateStoreRuns.updateCounterWithFlush();
+            cntConsolidateStoreRuns.increment();
             if (logger.isDebugEnabled()) {
                 logger.debug("Running consolidateStore.");
             }
@@ -2524,7 +2527,7 @@ IFlowReconcileListener, IInfoProvider {
             try {
                 iter = storeClient.entries();
             } catch (SyncException e) {
-                cntSyncException.updateCounterWithFlush();
+                cntSyncException.increment();
                 logger.error("Failed to read devices from sync store", e);
                 return;
             }
@@ -2561,7 +2564,7 @@ IFlowReconcileListener, IInfoProvider {
                                          + "corresponding live device",
                                          storedDevice.getKey());
                         }
-                        cntConsolidateStoreDevicesRemoved.updateCounterWithFlush();
+                        cntConsolidateStoreDevicesRemoved.increment();
                         removeDevice(versionedDevice);
                     }
                 }
@@ -2596,24 +2599,24 @@ IFlowReconcileListener, IInfoProvider {
      */
     private class DeviceEvent {
         @EventColumn(name = "MAC", description = EventFieldType.MAC)
-        private final long macAddress;
-        @EventColumn(name = "IPs", description = EventFieldType.LIST_IPV4)
-        private final List<Integer> ipv4Addresses;
+        private final MacAddress macAddress;
+        @EventColumn(name = "IPs", description = EventFieldType.IPv4)
+        private final List<IPv4Address> ipv4Addresses;
         @EventColumn(name = "Old Attachment Points",
-                     description = EventFieldType.LIST_ATTACHMENT_POINT)
+                     description = EventFieldType.COLLECTION_ATTACHMENT_POINT)
         private final List<SwitchPort> oldAttachmentPoints;
         @EventColumn(name = "Current Attachment Points",
-                     description = EventFieldType.LIST_ATTACHMENT_POINT)
+                     description = EventFieldType.COLLECTION_ATTACHMENT_POINT)
         private final List<SwitchPort> currentAttachmentPoints;
-        @EventColumn(name = "VLAN IDs", description = EventFieldType.LIST_OBJECT)
-        private final List<Short> vlanIds;
+        @EventColumn(name = "VLAN IDs", description = EventFieldType.COLLECTION_OBJECT)
+        private final List<VlanVid> vlanIds;
         @EventColumn(name = "Reason", description = EventFieldType.STRING)
         private final String reason;
 
-        public DeviceEvent(long macAddress, List<Integer> ipv4Addresses,
+        public DeviceEvent(MacAddress macAddress, List<IPv4Address> ipv4Addresses,
                 List<SwitchPort> oldAttachmentPoints,
                 List<SwitchPort> currentAttachmentPoints,
-                List<Short> vlanIds, String reason) {
+                List<VlanVid> vlanIds, String reason) {
             super();
             this.macAddress = macAddress;
             this.ipv4Addresses = ipv4Addresses;
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceSyncRepresentation.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceSyncRepresentation.java
index 42bfb0132..b1c395d4c 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceSyncRepresentation.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceSyncRepresentation.java
@@ -6,9 +6,14 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.EnumSet;
 import java.util.List;
-import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField;
 
+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 net.floodlightcontroller.devicemanager.SwitchPort;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
@@ -16,15 +21,15 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 public class DeviceSyncRepresentation {
     public static class SyncEntity implements Comparable<SyncEntity> {
         @JsonProperty
-        public long macAddress;
+        public MacAddress macAddress;
         @JsonProperty
-        public Integer ipv4Address;
+        public IPv4Address ipv4Address;
         @JsonProperty
-        public Short vlan;
+        public VlanVid vlan;
         @JsonProperty
-        public Long switchDPID;
+        public DatapathId switchDPID;
         @JsonProperty
-        public Integer switchPort;
+        public OFPort switchPort;
         @JsonProperty
         public Date lastSeenTimestamp;
         @JsonProperty
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java
index db8d8e9fb..39a8d79cd 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Entity.java
@@ -22,11 +22,15 @@ import java.util.Date;
 import net.floodlightcontroller.core.web.serializers.IPv4Serializer;
 import net.floodlightcontroller.core.web.serializers.MACSerializer;
 import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
-import net.floodlightcontroller.packet.IPv4;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.openflow.util.HexString;
+
+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;
 
 /**
  * An entity on the network is a visible trace of a device that corresponds
@@ -52,30 +56,30 @@ public class Entity implements Comparable<Entity> {
     /**
      * The MAC address associated with this entity
      */
-    protected long macAddress;
+    protected MacAddress macAddress;
     
     /**
      * The IP address associated with this entity, or null if no IP learned
      * from the network observation associated with this entity
      */
-    protected Integer ipv4Address;
+    protected IPv4Address ipv4Address;
     
     /**
      * The VLAN tag on this entity, or null if untagged
      */
-    protected Short vlan;
+    protected VlanVid vlan;
     
     /**
      * The DPID of the switch for the ingress point for this entity,
      * or null if not present
      */
-    protected Long switchDPID;
+    protected DatapathId switchDPID;
     
     /**
      * The port number of the switch for the ingress point for this entity,
      * or null if not present
      */
-    protected Integer switchPort;
+    protected OFPort switchPort;
     
     /**
      * The last time we observed this entity on the network
@@ -108,8 +112,8 @@ public class Entity implements Comparable<Entity> {
      * @param switchPort
      * @param lastSeenTimestamp
      */
-    public Entity(long macAddress, Short vlan, 
-                  Integer ipv4Address, Long switchDPID, Integer switchPort, 
+    public Entity(MacAddress macAddress, VlanVid vlan, 
+                  IPv4Address ipv4Address, DatapathId switchDPID, OFPort switchPort, 
                   Date lastSeenTimestamp) {
         this.macAddress = macAddress;
         this.ipv4Address = ipv4Address;
@@ -125,25 +129,25 @@ public class Entity implements Comparable<Entity> {
     // ***************
 
     @JsonSerialize(using=MACSerializer.class)
-    public long getMacAddress() {
+    public MacAddress getMacAddress() {
         return macAddress;
     }
 
     @JsonSerialize(using=IPv4Serializer.class)
-    public Integer getIpv4Address() {
+    public IPv4Address getIpv4Address() {
         return ipv4Address;
     }
 
-    public Short getVlan() {
+    public VlanVid getVlan() {
         return vlan;
     }
 
     @JsonSerialize(using=DPIDSerializer.class)
-    public Long getSwitchDPID() {
+    public DatapathId getSwitchDPID() {
         return switchDPID;
     }
 
-    public Integer getSwitchPort() {
+    public OFPort getSwitchPort() {
         return switchPort;
     }
     
@@ -185,7 +189,7 @@ public class Entity implements Comparable<Entity> {
         hashCode = 1;
         hashCode = prime * hashCode
                  + ((ipv4Address == null) ? 0 : ipv4Address.hashCode());
-        hashCode = prime * hashCode + (int) (macAddress ^ (macAddress >>> 32));
+        hashCode = prime * hashCode + (int) (macAddress.getLong() ^ (macAddress.getLong() >>> 32));
         hashCode = prime * hashCode
                  + ((switchDPID == null) ? 0 : switchDPID.hashCode());
         hashCode = prime * hashCode
@@ -223,16 +227,15 @@ public class Entity implements Comparable<Entity> {
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("Entity [macAddress=");
-        builder.append(HexString.toHexString(macAddress, 6));
+        builder.append(macAddress.toString());
         builder.append(", ipv4Address=");
-        builder.append(IPv4.fromIPv4Address(ipv4Address==null ?
-                       0 : ipv4Address.intValue()));
+        builder.append(ipv4Address.toString());
         builder.append(", vlan=");
-        builder.append(vlan);
+        builder.append(vlan.getVlan());
         builder.append(", switchDPID=");
-        builder.append(switchDPID);
+        builder.append(switchDPID.toString());
         builder.append(", switchPort=");
-        builder.append(switchPort);
+        builder.append(switchPort.getPortNumber());
         builder.append(", lastSeenTimestamp=");
         builder.append(lastSeenTimestamp == null? "null" : lastSeenTimestamp.getTime());
         builder.append(", activeSince=");
@@ -243,8 +246,8 @@ public class Entity implements Comparable<Entity> {
 
     @Override
     public int compareTo(Entity o) {
-        if (macAddress < o.macAddress) return -1;
-        if (macAddress > o.macAddress) return 1;
+        if (macAddress.getLong() < o.macAddress.getLong()) return -1;
+        if (macAddress.getLong() > o.macAddress.getLong()) return 1;
 
         int r;
         if (switchDPID == null)
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/IndexedEntity.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/IndexedEntity.java
index 13a78a49a..a1e7160b2 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/IndexedEntity.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/IndexedEntity.java
@@ -89,8 +89,8 @@ public class IndexedEntity {
             switch (f) {
                 case MAC:
                     hashCode = prime * hashCode
-                        + (int) (entity.macAddress ^ 
-                                (entity.macAddress >>> 32));
+                        + (int) (entity.macAddress.getLong() ^ 
+                                (entity.macAddress.getLong() >>> 32));
                     break;
                 case IPV4:
                     hashCode = prime * hashCode
diff --git a/src/main/java/net/floodlightcontroller/firewall/Firewall.java b/src/main/java/net/floodlightcontroller/firewall/Firewall.java
index 21dc8aed6..6b6b5578f 100644
--- a/src/main/java/net/floodlightcontroller/firewall/Firewall.java
+++ b/src/main/java/net/floodlightcontroller/firewall/Firewall.java
@@ -24,9 +24,16 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.IPv4AddressWithMask;
+import org.projectfloodlight.openflow.types.IpProtocol;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TransportPort;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IOFMessageListener;
@@ -35,11 +42,11 @@ 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.core.IFloodlightProviderService;
 import net.floodlightcontroller.devicemanager.IDeviceService;
 
 import java.util.ArrayList;
+
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPv4;
 import net.floodlightcontroller.restserver.IRestApiService;
@@ -184,7 +191,7 @@ public class Firewall implements IFirewallService, IOFMessageListener,
                 try {
                     r.ruleid = Integer
                             .parseInt((String) row.get(COLUMN_RULEID));
-                    r.dpid = Long.parseLong((String) row.get(COLUMN_DPID));
+                    r.dpid = DatapathId.of((String) row.get(COLUMN_DPID));
 
                     for (String key : row.keySet()) {
                         if (row.get(key) == null)
@@ -196,58 +203,58 @@ public class Firewall implements IFirewallService, IOFMessageListener,
                         } 
                         
                         else if (key.equals(COLUMN_IN_PORT)) {
-                            r.in_port = Short.parseShort((String) row
-                                    .get(COLUMN_IN_PORT));
+                            r.in_port = OFPort.of(Integer.parseInt((String) row
+                                    .get(COLUMN_IN_PORT)));
                         } 
                         
                         else if (key.equals(COLUMN_DL_SRC)) {
-                            r.dl_src = Long.parseLong((String) row
-                                    .get(COLUMN_DL_SRC));
+                            r.dl_src = MacAddress.of(Long.parseLong((String) row
+                                    .get(COLUMN_DL_SRC)));
                         } 
                         
                         else if (key.equals(COLUMN_DL_DST)) {
-                            r.dl_dst = Long.parseLong((String) row
-                                    .get(COLUMN_DL_DST));
+                            r.dl_dst = MacAddress.of(Long.parseLong((String) row
+                                    .get(COLUMN_DL_DST)));
                         } 
                         
                         else if (key.equals(COLUMN_DL_TYPE)) {
-                            r.dl_type = Short.parseShort((String) row
-                                    .get(COLUMN_DL_TYPE));
+                            r.dl_type = EthType.of(Integer.parseInt((String) row
+                                    .get(COLUMN_DL_TYPE)));
                         } 
                         
                         else if (key.equals(COLUMN_NW_SRC_PREFIX)) {
-                            r.nw_src_prefix = Integer.parseInt((String) row
-                                    .get(COLUMN_NW_SRC_PREFIX));
+                            r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(Integer.parseInt((String) row
+                                    .get(COLUMN_NW_SRC_PREFIX)), r.nw_src_prefix_and_mask.getMask().getInt());
                         } 
                         
                         else if (key.equals(COLUMN_NW_SRC_MASKBITS)) {
-                            r.nw_src_maskbits = Integer.parseInt((String) row
-                                    .get(COLUMN_NW_SRC_MASKBITS));
+                            r.nw_src_prefix_and_mask = IPv4AddressWithMask.of(r.nw_src_prefix_and_mask.getValue().getInt(), Integer.parseInt((String) row
+                                    .get(COLUMN_NW_SRC_MASKBITS)));
                         } 
                         
                         else if (key.equals(COLUMN_NW_DST_PREFIX)) {
-                            r.nw_dst_prefix = Integer.parseInt((String) row
-                                    .get(COLUMN_NW_DST_PREFIX));
+                            r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(Integer.parseInt((String) row
+                                    .get(COLUMN_NW_DST_PREFIX)), r.nw_dst_prefix_and_mask.getMask().getInt());
                         } 
                         
                         else if (key.equals(COLUMN_NW_DST_MASKBITS)) {
-                            r.nw_dst_maskbits = Integer.parseInt((String) row
-                                    .get(COLUMN_NW_DST_MASKBITS));
+                            r.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(r.nw_dst_prefix_and_mask.getValue().getInt(), Integer.parseInt((String) row
+                                    .get(COLUMN_NW_DST_MASKBITS)));
                         } 
                         
                         else if (key.equals(COLUMN_NW_PROTO)) {
-                            r.nw_proto = Short.parseShort((String) row
-                                    .get(COLUMN_NW_PROTO));
+                            r.nw_proto = IpProtocol.of(Short.parseShort((String) row
+                                    .get(COLUMN_NW_PROTO)));
                         } 
                         
                         else if (key.equals(COLUMN_TP_SRC)) {
-                            r.tp_src = Short.parseShort((String) row
-                                    .get(COLUMN_TP_SRC));
+                            r.tp_src = TransportPort.of(Integer.parseInt((String) row
+                                    .get(COLUMN_TP_SRC)));
                         } 
                         
                         else if (key.equals(COLUMN_TP_DST)) {
-                            r.tp_dst = Short.parseShort((String) row
-                                    .get(COLUMN_TP_DST));
+                            r.tp_dst = TransportPort.of(Integer.parseInt((String) row
+                                    .get(COLUMN_TP_DST)));
                         } 
                         
                         else if (key.equals(COLUMN_WILDCARD_DPID)) {
@@ -452,18 +459,18 @@ public class Firewall implements IFirewallService, IOFMessageListener,
         // add rule to database
         Map<String, Object> entry = new HashMap<String, Object>();
         entry.put(COLUMN_RULEID, Integer.toString(rule.ruleid));
-        entry.put(COLUMN_DPID, Long.toString(rule.dpid));
-        entry.put(COLUMN_IN_PORT, Short.toString(rule.in_port));
-        entry.put(COLUMN_DL_SRC, Long.toString(rule.dl_src));
-        entry.put(COLUMN_DL_DST, Long.toString(rule.dl_dst));
-        entry.put(COLUMN_DL_TYPE, Short.toString(rule.dl_type));
-        entry.put(COLUMN_NW_SRC_PREFIX, Integer.toString(rule.nw_src_prefix));
-        entry.put(COLUMN_NW_SRC_MASKBITS, Integer.toString(rule.nw_src_maskbits));
-        entry.put(COLUMN_NW_DST_PREFIX, Integer.toString(rule.nw_dst_prefix));
-        entry.put(COLUMN_NW_DST_MASKBITS, Integer.toString(rule.nw_dst_maskbits));
-        entry.put(COLUMN_NW_PROTO, Short.toString(rule.nw_proto));
-        entry.put(COLUMN_TP_SRC, Integer.toString(rule.tp_src));
-        entry.put(COLUMN_TP_DST, Integer.toString(rule.tp_dst));
+        entry.put(COLUMN_DPID, Long.toString(rule.dpid.getLong()));
+        entry.put(COLUMN_IN_PORT, Integer.toString(rule.in_port.getPortNumber()));
+        entry.put(COLUMN_DL_SRC, Long.toString(rule.dl_src.getLong()));
+        entry.put(COLUMN_DL_DST, Long.toString(rule.dl_dst.getLong()));
+        entry.put(COLUMN_DL_TYPE, Integer.toString(rule.dl_type.getValue()));
+        entry.put(COLUMN_NW_SRC_PREFIX, Integer.toString(rule.nw_src_prefix_and_mask.getValue().getInt()));
+        entry.put(COLUMN_NW_SRC_MASKBITS, Integer.toString(rule.nw_src_prefix_and_mask.getMask().getInt()));
+        entry.put(COLUMN_NW_DST_PREFIX, Integer.toString(rule.nw_dst_prefix_and_mask.getValue().getInt()));
+        entry.put(COLUMN_NW_DST_MASKBITS, Integer.toString(rule.nw_dst_prefix_and_mask.getMask().getInt()));
+        entry.put(COLUMN_NW_PROTO, Short.toString(rule.nw_proto.getIpProtocolNumber()));
+        entry.put(COLUMN_TP_SRC, Integer.toString(rule.tp_src.getPort()));
+        entry.put(COLUMN_TP_DST, Integer.toString(rule.tp_dst.getPort()));
         entry.put(COLUMN_WILDCARD_DPID,
                 Boolean.toString(rule.wildcard_dpid));
         entry.put(COLUMN_WILDCARD_IN_PORT,
diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java
index f457ce8d9..bee8fddef 100644
--- a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java
+++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java
@@ -18,7 +18,15 @@
 package net.floodlightcontroller.firewall;
 
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.openflow.protocol.OFMatch;
+
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.IPv4AddressWithMask;
+import org.projectfloodlight.openflow.types.IpProtocol;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TransportPort;
 
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPacket;
@@ -30,18 +38,18 @@ import net.floodlightcontroller.packet.UDP;
 public class FirewallRule implements Comparable<FirewallRule> {
     public int ruleid;
 
-    public long dpid; 
-    public short in_port; 
-    public long dl_src; 
-    public long dl_dst; 
-    public short dl_type; 
-    public int nw_src_prefix; 
-    public int nw_src_maskbits;
-    public int nw_dst_prefix;
-    public int nw_dst_maskbits;
-    public short nw_proto;
-    public short tp_src;
-    public short tp_dst;
+    public DatapathId dpid; 
+    public OFPort in_port; 
+    public MacAddress dl_src; 
+    public MacAddress dl_dst; 
+    public EthType dl_type; 
+    public IPv4AddressWithMask nw_src_prefix_and_mask; 
+    //public int nw_src_maskbits;
+    public IPv4AddressWithMask nw_dst_prefix_and_mask;
+    //public int nw_dst_maskbits;
+    public IpProtocol nw_proto;
+    public TransportPort tp_src;
+    public TransportPort tp_dst;
 
     public boolean wildcard_dpid;
     public boolean wildcard_in_port; 
@@ -67,18 +75,18 @@ public class FirewallRule implements Comparable<FirewallRule> {
     }
 
     public FirewallRule() {
-        this.in_port = 0; 
-        this.dl_src = 0;
-        this.nw_src_prefix = 0;
-        this.nw_src_maskbits = 0; 
-        this.dl_dst = 0;
-        this.nw_proto = 0;
-        this.tp_src = 0;
-        this.tp_dst = 0;
-        this.dl_dst = 0;
-        this.nw_dst_prefix = 0;
-        this.nw_dst_maskbits = 0; 
-        this.dpid = -1;
+        this.in_port = OFPort.ZERO; 
+        this.dl_src = MacAddress.NONE;
+        this.nw_src_prefix_and_mask = IPv4AddressWithMask.NONE;
+        //this.nw_src_maskbits = 0; 
+        this.dl_dst = MacAddress.NONE;
+        this.nw_proto = IpProtocol.NONE;
+        this.tp_src = TransportPort.NONE;
+        this.tp_dst = TransportPort.NONE;
+        this.dl_dst = MacAddress.NONE;
+        this.nw_dst_prefix_and_mask = IPv4AddressWithMask.NONE;
+        //this.nw_dst_maskbits = 0; 
+        this.dpid = DatapathId.NONE;
         this.wildcard_dpid = true; 
         this.wildcard_in_port = true; 
         this.wildcard_dl_src = true; 
@@ -88,7 +96,7 @@ public class FirewallRule implements Comparable<FirewallRule> {
         this.wildcard_nw_dst = true; 
         this.wildcard_nw_proto = true; 
         this.wildcard_tp_src = true; 
-        this.wildcard_tp_dst = true; 
+        this.wildcard_tp_dst = true;
         this.priority = 0; 
         this.action = FirewallAction.ALLOW; 
         this.ruleid = 0; 
@@ -132,23 +140,23 @@ public class FirewallRule implements Comparable<FirewallRule> {
     public boolean isSameAs(FirewallRule r) {
         if (this.action != r.action
                 || this.wildcard_dl_type != r.wildcard_dl_type
-                || (this.wildcard_dl_type == false && this.dl_type != r.dl_type)
+                || (this.wildcard_dl_type == false && !this.dl_type.equals(r.dl_type))
                 || this.wildcard_tp_src != r.wildcard_tp_src
-                || (this.wildcard_tp_src == false && this.tp_src != r.tp_src)
+                || (this.wildcard_tp_src == false && !this.tp_src.equals(r.tp_src))
                 || this.wildcard_tp_dst != r.wildcard_tp_dst
-                || (this.wildcard_tp_dst == false &&this.tp_dst != r.tp_dst)
+                || (this.wildcard_tp_dst == false && !this.tp_dst.equals(r.tp_dst))
                 || this.wildcard_dpid != r.wildcard_dpid
-                || (this.wildcard_dpid == false && this.dpid != r.dpid)
+                || (this.wildcard_dpid == false && !this.dpid.equals(r.dpid))
                 || this.wildcard_in_port != r.wildcard_in_port
-                || (this.wildcard_in_port == false && this.in_port != r.in_port)
+                || (this.wildcard_in_port == false && !this.in_port.equals(r.in_port))
                 || this.wildcard_nw_src != r.wildcard_nw_src
-                || (this.wildcard_nw_src == false && (this.nw_src_prefix != r.nw_src_prefix || this.nw_src_maskbits != r.nw_src_maskbits))
+                || (this.wildcard_nw_src == false && !this.nw_src_prefix_and_mask.equals(r.nw_src_prefix_and_mask))
                 || this.wildcard_dl_src != r.wildcard_dl_src
-                || (this.wildcard_dl_src == false && this.dl_src != r.dl_src)
+                || (this.wildcard_dl_src == false && !this.dl_src.equals(r.dl_src))
                 || this.wildcard_nw_proto != r.wildcard_nw_proto
-                || (this.wildcard_nw_proto == false && this.nw_proto != r.nw_proto)
+                || (this.wildcard_nw_proto == false && !this.nw_proto.equals(r.nw_proto))
                 || this.wildcard_nw_dst != r.wildcard_nw_dst
-                || (this.wildcard_nw_dst == false && (this.nw_dst_prefix != r.nw_dst_prefix || this.nw_dst_maskbits != r.nw_dst_maskbits))
+                || (this.wildcard_nw_dst == false && !this.nw_dst_prefix_and_mask.equals(r.nw_dst_prefix_and_mask))
                 || this.wildcard_dl_dst != r.wildcard_dl_dst                
                 || (this.wildcard_dl_dst == false && this.dl_dst != r.dl_dst)) {
             return false;
@@ -171,7 +179,7 @@ public class FirewallRule implements Comparable<FirewallRule> {
      *            method to derive wildcards for the decision to be taken
      * @return true if the rule matches the given packet-in, false otherwise
      */
-    public boolean matchesFlow(long switchDpid, short inPort, Ethernet packet,
+    public boolean matchesFlow(DatapathId switchDpid, OFPort inPort, Ethernet packet,
             WildcardsPair wildcards) {
         IPacket pkt = packet.getPayload();
 
@@ -187,35 +195,39 @@ public class FirewallRule implements Comparable<FirewallRule> {
         short pkt_tp_dst = 0;
 
         // switchID matches?
-        if (wildcard_dpid == false && dpid != switchDpid)
+        if (wildcard_dpid == false && !dpid.equals(switchDpid))
             return false;
 
         // in_port matches?
-        if (wildcard_in_port == false && in_port != inPort)
+        if (wildcard_in_port == false && !in_port.equals(inPort))
             return false;
         if (action == FirewallRule.FirewallAction.DENY) {
-            wildcards.drop &= ~OFMatch.OFPFW_IN_PORT;
+            //wildcards.drop &= ~OFMatch.OFPFW_IN_PORT;
+            wildcards.drop.setExact(MatchField.IN_PORT, this.in_port);
         } else {
-            wildcards.allow &= ~OFMatch.OFPFW_IN_PORT;
+            //wildcards.allow &= ~OFMatch.OFPFW_IN_PORT;
+            wildcards.allow.setExact(MatchField.IN_PORT, this.in_port);
         }
 
         // mac address (src and dst) match?
-        if (wildcard_dl_src == false
-                && dl_src != packet.getSourceMAC().toLong())
+        if (wildcard_dl_src == false && !dl_src.equals(packet.getSourceMAC()))
             return false;
         if (action == FirewallRule.FirewallAction.DENY) {
-            wildcards.drop &= ~OFMatch.OFPFW_DL_SRC;
+            //wildcards.drop &= ~OFMatch.OFPFW_DL_SRC;
+            wildcards.drop.setExact(MatchField.ETH_SRC, this.dl_src);
         } else {
-            wildcards.allow &= ~OFMatch.OFPFW_DL_SRC;
+            //wildcards.allow &= ~OFMatch.OFPFW_DL_SRC;
+            wildcards.allow.setExact(MatchField.ETH_SRC, this.dl_src);
         }
 
-        if (wildcard_dl_dst == false
-                && dl_dst != packet.getDestinationMAC().toLong())
+        if (wildcard_dl_dst == false && !dl_dst.equals(packet.getDestinationMAC()))
             return false;
         if (action == FirewallRule.FirewallAction.DENY) {
-            wildcards.drop &= ~OFMatch.OFPFW_DL_DST;
+            //wildcards.drop &= ~OFMatch.OFPFW_DL_DST;
+            wildcards.drop.setExact(MatchField.ETH_DST, this.dl_dst);
         } else {
-            wildcards.allow &= ~OFMatch.OFPFW_DL_DST;
+            //wildcards.allow &= ~OFMatch.OFPFW_DL_DST;
+            wildcards.allow.setExact(MatchField.ETH_DST, this.dl_dst);
         }
 
         // dl_type check: ARP, IP
@@ -223,103 +235,128 @@ public class FirewallRule implements Comparable<FirewallRule> {
         // if this is not an ARP rule but the pkt is ARP,
         // return false match - no need to continue protocol specific check
         if (wildcard_dl_type == false) {
-            if (dl_type == Ethernet.TYPE_ARP) {
-                if (packet.getEtherType() != Ethernet.TYPE_ARP)
+            if (dl_type.equals(EthType.ARP)) {
+                if (packet.getEtherType() != EthType.ARP.getValue())
                     return false;
                 else {
                     if (action == FirewallRule.FirewallAction.DENY) {
-                        wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE;
+                        //wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE;
+                        wildcards.drop.setExact(MatchField.ETH_TYPE, this.dl_type);
                     } else {
-                        wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE;
+                        //wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE;
+                        wildcards.allow.setExact(MatchField.ETH_TYPE, this.dl_type);
                     }
                 }
-            } else if (dl_type == Ethernet.TYPE_IPv4) {
-                if (packet.getEtherType() != Ethernet.TYPE_IPv4)
+            } else if (dl_type.equals(EthType.IPv4)) {
+                if (packet.getEtherType() != EthType.IPv4.getValue())
                     return false;
                 else {
                     if (action == FirewallRule.FirewallAction.DENY) {
-                        wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO;
+                        //wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO;
+                        wildcards.drop.setExact(MatchField.IP_PROTO, this.nw_proto);
                     } else {
-                        wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO;
+                        //wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO;
+                        wildcards.allow.setExact(MatchField.IP_PROTO, this.nw_proto);
                     }
                     // IP packets, proceed with ip address check
                     pkt_ip = (IPv4) pkt;
 
                     // IP addresses (src and dst) match?
-                    if (wildcard_nw_src == false
-                            && this.matchIPAddress(nw_src_prefix,
-                                    nw_src_maskbits, pkt_ip.getSourceAddress()) == false)
+                    if (wildcard_nw_src == false && this.matchIPAddress(nw_src_prefix_and_mask.getValue().getInt(), nw_src_prefix_and_mask.getMask().getInt(), pkt_ip.getSourceAddress()) == false)
                         return false;
                     if (action == FirewallRule.FirewallAction.DENY) {
-                        wildcards.drop &= ~OFMatch.OFPFW_NW_SRC_ALL;
-                        wildcards.drop |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT);
+                        //wildcards.drop &= ~OFMatch.OFPFW_NW_SRC_ALL;
+                        //wildcards.drop |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT);
+                    	wildcards.drop.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask);
                     } else {
-                        wildcards.allow &= ~OFMatch.OFPFW_NW_SRC_ALL;
-                        wildcards.allow |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT);
+                        //wildcards.allow &= ~OFMatch.OFPFW_NW_SRC_ALL;
+                        //wildcards.allow |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT);
+                    	wildcards.allow.setMasked(MatchField.IPV4_SRC, nw_src_prefix_and_mask);
                     }
 
-                    if (wildcard_nw_dst == false
-                            && this.matchIPAddress(nw_dst_prefix,
-                                    nw_dst_maskbits,
-                                    pkt_ip.getDestinationAddress()) == false)
+                    if (wildcard_nw_dst == false && this.matchIPAddress(nw_dst_prefix_and_mask.getValue().getInt(), nw_dst_prefix_and_mask.getMask().getInt(), pkt_ip.getDestinationAddress()) == false)
                         return false;
                     if (action == FirewallRule.FirewallAction.DENY) {
-                        wildcards.drop &= ~OFMatch.OFPFW_NW_DST_ALL;
-                        wildcards.drop |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT);
+                        //wildcards.drop &= ~OFMatch.OFPFW_NW_DST_ALL;
+                        //wildcards.drop |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT);
+                    	wildcards.drop.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask);
                     } else {
-                        wildcards.allow &= ~OFMatch.OFPFW_NW_DST_ALL;
-                        wildcards.allow |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT);
+                        //wildcards.allow &= ~OFMatch.OFPFW_NW_DST_ALL;
+                        //wildcards.allow |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT);
+                    	wildcards.allow.setMasked(MatchField.IPV4_DST, nw_dst_prefix_and_mask);
                     }
 
                     // nw_proto check
                     if (wildcard_nw_proto == false) {
-                        if (nw_proto == IPv4.PROTOCOL_TCP) {
-                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_TCP)
+                        if (nw_proto.equals(IpProtocol.TCP)) {
+                            if ((short) pkt_ip.getProtocol() != IpProtocol.TCP.getIpProtocolNumber())
                                 return false;
                             else {
                                 pkt_tcp = (TCP) pkt_ip.getPayload();
                                 pkt_tp_src = pkt_tcp.getSourcePort();
                                 pkt_tp_dst = pkt_tcp.getDestinationPort();
                             }
-                        } else if (nw_proto == IPv4.PROTOCOL_UDP) {
-                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_UDP)
+                        } else if (nw_proto.equals(IpProtocol.UDP)) {
+                            if ((short) pkt_ip.getProtocol() != IpProtocol.UDP.getIpProtocolNumber())
                                 return false;
                             else {
                                 pkt_udp = (UDP) pkt_ip.getPayload();
                                 pkt_tp_src = pkt_udp.getSourcePort();
                                 pkt_tp_dst = pkt_udp.getDestinationPort();
                             }
-                        } else if (nw_proto == IPv4.PROTOCOL_ICMP) {
-                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_ICMP)
+                        } else if (nw_proto.equals(IpProtocol.ICMP)) {
+                            if ((short) pkt_ip.getProtocol() != IpProtocol.ICMP.getIpProtocolNumber())
                                 return false;
                             else {
                                 // nothing more needed for ICMP
                             }
                         }
                         if (action == FirewallRule.FirewallAction.DENY) {
-                            wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO;
+                            //wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO;
+                            wildcards.drop.setExact(MatchField.IP_PROTO, this.nw_proto);
                         } else {
-                            wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO;
+                            //wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO;
+                            wildcards.allow.setExact(MatchField.IP_PROTO, this.nw_proto);
                         }
 
                         // TCP/UDP source and destination ports match?
                         if (pkt_tcp != null || pkt_udp != null) {
                             // does the source port match?
-                            if (tp_src != 0 && tp_src != pkt_tp_src)
+                            if (tp_src.getPort() != 0 && tp_src.getPort() != pkt_tp_src)
                                 return false;
                             if (action == FirewallRule.FirewallAction.DENY) {
-                                wildcards.drop &= ~OFMatch.OFPFW_TP_SRC;
+                                //wildcards.drop &= ~OFMatch.OFPFW_TP_SRC;
+                                if (pkt_tcp != null) {
+                                	wildcards.drop.setExact(MatchField.TCP_SRC, this.tp_src);
+                                } else {
+                                	wildcards.drop.setExact(MatchField.UDP_SRC, this.tp_src);   
+                                }
                             } else {
-                                wildcards.allow &= ~OFMatch.OFPFW_TP_SRC;
+                                //wildcards.allow &= ~OFMatch.OFPFW_TP_SRC;
+                                if (pkt_tcp != null) {
+                                	wildcards.allow.setExact(MatchField.TCP_SRC, this.tp_src);
+                                } else {
+                                	wildcards.allow.setExact(MatchField.UDP_SRC, this.tp_src);   
+                                }
                             }
 
                             // does the destination port match?
-                            if (tp_dst != 0 && tp_dst != pkt_tp_dst)
+                            if (tp_dst.getPort() != 0 && tp_dst.getPort() != pkt_tp_dst)
                                 return false;
                             if (action == FirewallRule.FirewallAction.DENY) {
-                                wildcards.drop &= ~OFMatch.OFPFW_TP_DST;
+                                //wildcards.drop &= ~OFMatch.OFPFW_TP_DST;
+                                if (pkt_tcp != null) {
+                                	wildcards.drop.setExact(MatchField.TCP_DST, this.tp_dst);
+                                } else {
+                                	wildcards.drop.setExact(MatchField.UDP_DST, this.tp_dst);   
+                                }
                             } else {
-                                wildcards.allow &= ~OFMatch.OFPFW_TP_DST;
+                                //wildcards.allow &= ~OFMatch.OFPFW_TP_DST;
+                            	if (pkt_tcp != null) {
+                                	wildcards.allow.setExact(MatchField.TCP_DST, this.tp_dst);
+                                } else {
+                                	wildcards.allow.setExact(MatchField.UDP_DST, this.tp_dst);   
+                                }
                             }
                         }
                     }
@@ -331,9 +368,11 @@ public class FirewallRule implements Comparable<FirewallRule> {
             }
         }
         if (action == FirewallRule.FirewallAction.DENY) {
-            wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE;
+            //wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE;
+        	wildcards.drop.setExact(MatchField.ETH_TYPE, this.dl_type);
         } else {
-            wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE;
+            //wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE;
+        	wildcards.allow.setExact(MatchField.ETH_TYPE, this.dl_type);
         }
 
         // all applicable checks passed
@@ -382,18 +421,18 @@ public class FirewallRule implements Comparable<FirewallRule> {
     public int hashCode() {
         final int prime = 2521;
         int result = super.hashCode();
-        result = prime * result + (int) dpid;
-        result = prime * result + in_port;
-        result = prime * result + (int) dl_src;
-        result = prime * result + (int) dl_dst;
-        result = prime * result + dl_type;
-        result = prime * result + nw_src_prefix;
-        result = prime * result + nw_src_maskbits;
-        result = prime * result + nw_dst_prefix;
-        result = prime * result + nw_dst_maskbits;
-        result = prime * result + nw_proto;
-        result = prime * result + tp_src;
-        result = prime * result + tp_dst;
+        result = prime * result + (int) dpid.getLong();
+        result = prime * result + in_port.getPortNumber();
+        result = prime * result + (int) dl_src.getLong();
+        result = prime * result + (int) dl_dst.getLong();
+        result = prime * result + dl_type.getValue();
+        result = prime * result + nw_src_prefix_and_mask.getValue().getInt();
+        result = prime * result + nw_src_prefix_and_mask.getMask().getInt();
+        result = prime * result + nw_dst_prefix_and_mask.getValue().getInt();
+        result = prime * result + nw_dst_prefix_and_mask.getMask().getInt();
+        result = prime * result + nw_proto.getIpProtocolNumber();
+        result = prime * result + tp_src.getPort();
+        result = prime * result + tp_dst.getPort();
         result = prime * result + action.ordinal();
         result = prime * result + priority;
         result = prime * result + (new Boolean(wildcard_dpid)).hashCode();
diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRuleSerializer.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRuleSerializer.java
index 3180968d1..42cb2727f 100644
--- a/src/main/java/net/floodlightcontroller/firewall/FirewallRuleSerializer.java
+++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRuleSerializer.java
@@ -19,14 +19,10 @@ package net.floodlightcontroller.firewall;
 
 import java.io.IOException;
 
-import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.util.MACAddress;
-
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializerProvider;
-import org.openflow.util.HexString;
 
 /**
  * Serialize a FirewallRule object
@@ -42,18 +38,18 @@ public class FirewallRuleSerializer extends JsonSerializer<FirewallRule> {
         jGen.writeStartObject();
         
         jGen.writeNumberField("ruleid", rule.ruleid);
-        jGen.writeStringField("dpid", HexString.toHexString(rule.dpid));
-        jGen.writeNumberField("in_port", rule.in_port);
-        jGen.writeStringField("dl_src",String.valueOf(MACAddress.valueOf(rule.dl_src)));
-        jGen.writeStringField("dl_dst", String.valueOf(MACAddress.valueOf(rule.dl_dst)));
-        jGen.writeNumberField("dl_type", rule.dl_type);
-        jGen.writeStringField("nw_src_prefix", IPv4.fromIPv4Address(rule.nw_src_prefix));
-        jGen.writeNumberField("nw_src_maskbits", rule.nw_src_maskbits);
-        jGen.writeStringField("nw_dst_prefix", IPv4.fromIPv4Address(rule.nw_dst_prefix));
-        jGen.writeNumberField("nw_dst_maskbits", rule.nw_dst_maskbits);
-        jGen.writeNumberField("nw_proto", rule.nw_proto);
-        jGen.writeNumberField("tp_src", rule.tp_src);
-        jGen.writeNumberField("tp_dst", rule.tp_dst);
+        jGen.writeStringField("dpid", rule.dpid.toString());
+        jGen.writeNumberField("in_port", rule.in_port.getPortNumber());
+        jGen.writeStringField("dl_src", rule.dl_src.toString());
+        jGen.writeStringField("dl_dst", rule.dl_dst.toString());
+        jGen.writeNumberField("dl_type", rule.dl_type.getValue());
+        jGen.writeStringField("nw_src_prefix", rule.nw_src_prefix_and_mask.getValue().toString());
+        jGen.writeNumberField("nw_src_maskbits", rule.nw_src_prefix_and_mask.getMask().asCidrMaskLength());
+        jGen.writeStringField("nw_dst_prefix", rule.nw_dst_prefix_and_mask.getValue().toString());
+        jGen.writeNumberField("nw_dst_maskbits", rule.nw_dst_prefix_and_mask.getMask().asCidrMaskLength());
+        jGen.writeNumberField("nw_proto", rule.nw_proto.getIpProtocolNumber());
+        jGen.writeNumberField("tp_src", rule.tp_src.getPort());
+        jGen.writeNumberField("tp_dst", rule.tp_dst.getPort());
         jGen.writeBooleanField("wildcard_dpid", rule.wildcard_dpid);
         jGen.writeBooleanField("wildcard_in_port", rule.wildcard_in_port);
         jGen.writeBooleanField("wildcard_dl_src", rule.wildcard_dl_src);
diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java
index 7af219cc6..27e40d3ff 100644
--- a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java
+++ b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java
@@ -25,7 +25,14 @@ import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
 import com.fasterxml.jackson.databind.MappingJsonFactory;
-import org.openflow.util.HexString;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.IPv4AddressWithMask;
+import org.projectfloodlight.openflow.types.IpProtocol;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TransportPort;
 import org.restlet.resource.Delete;
 import org.restlet.resource.Post;
 import org.restlet.resource.Get;
@@ -33,7 +40,6 @@ import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPv4;
 
 public class FirewallRulesResource extends ServerResource {
@@ -166,13 +172,13 @@ public class FirewallRulesResource extends ServerResource {
                 tmp = jp.getText();
                 if (tmp.equalsIgnoreCase("-1") == false) {
                     // user inputs hex format dpid
-                    rule.dpid = HexString.toLong(tmp);
+                    rule.dpid = DatapathId.of(tmp);
                     rule.wildcard_dpid = false;
                 }
             }
 
             else if (n == "src-inport") {
-                rule.in_port = Short.parseShort(jp.getText());
+                rule.in_port = OFPort.of(Integer.parseInt(jp.getText()));
                 rule.wildcard_in_port = false;
             }
 
@@ -180,7 +186,7 @@ public class FirewallRulesResource extends ServerResource {
                 tmp = jp.getText();
                 if (tmp.equalsIgnoreCase("ANY") == false) {
                     rule.wildcard_dl_src = false;
-                    rule.dl_src = Ethernet.toLong(Ethernet.toMACAddress(tmp));
+                    rule.dl_src = MacAddress.of(tmp);
                 }
             }
 
@@ -188,7 +194,7 @@ public class FirewallRulesResource extends ServerResource {
                 tmp = jp.getText();
                 if (tmp.equalsIgnoreCase("ANY") == false) {
                     rule.wildcard_dl_dst = false;
-                    rule.dl_dst = Ethernet.toLong(Ethernet.toMACAddress(tmp));
+                    rule.dl_dst = MacAddress.of(tmp);
                 }
             }
 
@@ -196,11 +202,11 @@ public class FirewallRulesResource extends ServerResource {
                 tmp = jp.getText();
                 if (tmp.equalsIgnoreCase("ARP")) {
                     rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_ARP;
+                    rule.dl_type = EthType.ARP;
                 }
                 if (tmp.equalsIgnoreCase("IPv4")) {
                     rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
+                    rule.dl_type = EthType.IPv4;
                 }
             }
 
@@ -209,10 +215,8 @@ public class FirewallRulesResource extends ServerResource {
                 if (tmp.equalsIgnoreCase("ANY") == false) {
                     rule.wildcard_nw_src = false;
                     rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
-                    int[] cidr = IPCIDRToPrefixBits(tmp);
-                    rule.nw_src_prefix = cidr[0];
-                    rule.nw_src_maskbits = cidr[1];
+                    rule.dl_type = EthType.IPv4;
+                    rule.nw_src_prefix_and_mask = IPv4AddressWithMask.of(tmp);
                 }
             }
 
@@ -221,10 +225,8 @@ public class FirewallRulesResource extends ServerResource {
                 if (tmp.equalsIgnoreCase("ANY") == false) {
                     rule.wildcard_nw_dst = false;
                     rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
-                    int[] cidr = IPCIDRToPrefixBits(tmp);
-                    rule.nw_dst_prefix = cidr[0];
-                    rule.nw_dst_maskbits = cidr[1];
+                    rule.dl_type = EthType.IPv4;
+                    rule.nw_dst_prefix_and_mask = IPv4AddressWithMask.of(tmp);
                 }
             }
 
@@ -232,30 +234,30 @@ public class FirewallRulesResource extends ServerResource {
                 tmp = jp.getText();
                 if (tmp.equalsIgnoreCase("TCP")) {
                     rule.wildcard_nw_proto = false;
-                    rule.nw_proto = IPv4.PROTOCOL_TCP;
+                    rule.nw_proto = IpProtocol.TCP;
                     rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
+                    rule.dl_type = EthType.IPv4;
                 } else if (tmp.equalsIgnoreCase("UDP")) {
                     rule.wildcard_nw_proto = false;
-                    rule.nw_proto = IPv4.PROTOCOL_UDP;
+                    rule.nw_proto = IpProtocol.UDP;
                     rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
+                    rule.dl_type = EthType.IPv4;
                 } else if (tmp.equalsIgnoreCase("ICMP")) {
                     rule.wildcard_nw_proto = false;
-                    rule.nw_proto = IPv4.PROTOCOL_ICMP;
+                    rule.nw_proto = IpProtocol.ICMP;
                     rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
+                    rule.dl_type = EthType.IPv4;
                 }
             }
 
             else if (n == "tp-src") {
                 rule.wildcard_tp_src = false;
-                rule.tp_src = Short.parseShort(jp.getText());
+                rule.tp_src = TransportPort.of(Integer.parseInt(jp.getText()));
             }
 
             else if (n == "tp-dst") {
                 rule.wildcard_tp_dst = false;
-                rule.tp_dst = Short.parseShort(jp.getText());
+                rule.tp_dst = TransportPort.of(Integer.parseInt(jp.getText()));
             }
 
             else if (n == "priority") {
diff --git a/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java b/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java
index d2aa2e5ff..114dc3eee 100644
--- a/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java
+++ b/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java
@@ -17,9 +17,9 @@
 
 package net.floodlightcontroller.firewall;
 
-import org.openflow.protocol.OFMatch;
+import org.projectfloodlight.openflow.protocol.match.Match;
 
 public class RuleWildcardsPair {
     public FirewallRule rule;
-    public int wildcards = OFMatch.OFPFW_ALL;
+    public Match.Builder wildcards;
 }
diff --git a/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java b/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java
index db4cf7441..f6443c403 100644
--- a/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java
+++ b/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java
@@ -17,9 +17,12 @@
 
 package net.floodlightcontroller.firewall;
 
-import org.openflow.protocol.OFMatch;
+import org.projectfloodlight.openflow.protocol.match.Match;
+
 
 public class WildcardsPair {
-    public int allow = OFMatch.OFPFW_ALL;
-    public int drop = OFMatch.OFPFW_ALL;
+    //public int allow = OFMatch.OFPFW_ALL;
+    //public int drop = OFMatch.OFPFW_ALL;
+    public Match.Builder allow;
+    public Match.Builder drop;
 }
diff --git a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java
index 588e8bc31..40fc77bcf 100644
--- a/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java
+++ b/src/main/java/net/floodlightcontroller/forwarding/Forwarding.java
@@ -33,6 +33,7 @@ import net.floodlightcontroller.devicemanager.SwitchPort;
 import net.floodlightcontroller.core.annotations.LogMessageCategory;
 import net.floodlightcontroller.core.annotations.LogMessageDoc;
 import net.floodlightcontroller.core.annotations.LogMessageDocs;
+import net.floodlightcontroller.core.internal.IOFSwitchService;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
@@ -40,20 +41,30 @@ import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.AppCookie;
 import net.floodlightcontroller.counter.ICounterStoreService;
 import net.floodlightcontroller.packet.Ethernet;
+import net.floodlightcontroller.packet.IPv4;
 import net.floodlightcontroller.routing.ForwardingBase;
 import net.floodlightcontroller.routing.IRoutingDecision;
 import net.floodlightcontroller.routing.IRoutingService;
 import net.floodlightcontroller.routing.Route;
 import net.floodlightcontroller.topology.ITopologyService;
 
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFPacketIn;
-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.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFFlowModCommand;
+import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+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.OFVlanVidMatch;
+import org.projectfloodlight.openflow.types.VlanVid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -161,24 +172,29 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
     protected void doForwardFlow(IOFSwitch sw, OFPacketIn pi,
                                  FloodlightContext cntx,
                                  boolean requestFlowRemovedNotifn) {
-        OFMatch match = new OFMatch();
-        match.loadFromPacket(pi.getPacketData(), pi.getInPort());
-
+        //OFMatch match = new OFMatch();
+        //match.loadFromPacket(pi.getData(), pi.getInPort());
+        //Match.Builder matchBuilder = sw.getOFFactory().buildMatch();
+        Match match = pi.getMatch();
         // Check if we have the location of the destination
         IDevice dstDevice =
                 IDeviceService.fcStore.
                     get(cntx, IDeviceService.CONTEXT_DST_DEVICE);
 
+        // DESTINATION DEVICE = KNOWN
         if (dstDevice != null) {
             IDevice srcDevice =
                     IDeviceService.fcStore.
                         get(cntx, IDeviceService.CONTEXT_SRC_DEVICE);
-            Long srcIsland = topology.getL2DomainId(sw.getId());
+            DatapathId srcIsland = topology.getL2DomainId(sw.getId());
 
+            // If we can't find the source device, that's no good
             if (srcDevice == null) {
                 log.debug("No device entry found for source device");
                 return;
             }
+            
+            // If the source isn't connected to an OF island we control, then that's not good either
             if (srcIsland == null) {
                 log.debug("No openflow island found for source {}/{}",
                           sw.getStringId(), pi.getInPort());
@@ -186,24 +202,24 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
             }
 
             // Validate that we have a destination known on the same island
-            // Validate that the source and destination are not on the same switchport
+            // Validate that the source and destination are not on the same switch port
             boolean on_same_island = false;
             boolean on_same_if = false;
             for (SwitchPort dstDap : dstDevice.getAttachmentPoints()) {
-                long dstSwDpid = dstDap.getSwitchDPID();
-                Long dstIsland = topology.getL2DomainId(dstSwDpid);
+                DatapathId dstSwDpid = dstDap.getSwitchDPID();
+                DatapathId dstIsland = topology.getL2DomainId(dstSwDpid);
                 if ((dstIsland != null) && dstIsland.equals(srcIsland)) {
                     on_same_island = true;
-                    if ((sw.getId() == dstSwDpid) &&
-                        (pi.getInPort() == dstDap.getPort())) {
+                    if ((sw.getId().equals(dstSwDpid)) &&
+                        (pi.getInPort().equals(dstDap.getPort()))) {
                         on_same_if = true;
                     }
                     break;
                 }
             }
 
+            // If the two devices are not on the same L2 network, find out how to get to the destination via flooding
             if (!on_same_island) {
-                // Flood since we don't know the dst device
                 if (log.isTraceEnabled()) {
                     log.trace("No first hop island found for destination " +
                               "device {}, Action = flooding", dstDevice);
@@ -212,6 +228,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
                 return;
             }
 
+            // If the two devices are on the same switch port number, they should be able to communicate w/o further flows
             if (on_same_if) {
                 if (log.isTraceEnabled()) {
                     log.trace("Both source and destination are on the same " +
@@ -237,9 +254,9 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
 
                 // srcCluster and dstCluster here cannot be null as
                 // every switch will be at least in its own L2 domain.
-                Long srcCluster =
+                DatapathId srcCluster =
                         topology.getL2DomainId(srcDap.getSwitchDPID());
-                Long dstCluster =
+                DatapathId dstCluster =
                         topology.getL2DomainId(dstDap.getSwitchDPID());
 
                 int srcVsDest = srcCluster.compareTo(dstCluster);
@@ -247,9 +264,9 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
                     if (!srcDap.equals(dstDap)) {
                         Route route =
                                 routingEngine.getRoute(srcDap.getSwitchDPID(),
-                                                       (short)srcDap.getPort(),
+                                                       srcDap.getPort(),
                                                        dstDap.getSwitchDPID(),
-                                                       (short)dstDap.getPort(), 0); //cookie = 0, i.e., default route
+                                                       dstDap.getPort(), 0); //cookie = 0, i.e., default route
                         if (route != null) {
                             if (log.isTraceEnabled()) {
                                 log.trace("pushRoute match={} route={} " +
@@ -262,7 +279,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
                                     AppCookie.makeCookie(FORWARDING_APP_ID, 0);
 
                             // if there is prior routing decision use wildcard
-                            Integer wildcard_hints = null;
+                            Match.Builder wildcard_hints;
                             IRoutingDecision decision = null;
                             if (cntx != null) {
                                 decision = IRoutingDecision.rtStore
@@ -273,7 +290,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
                                 wildcard_hints = decision.getWildcards();
                             } else {
                             	// L2 only wildcard if there is no prior route decision
-                                wildcard_hints = ((Integer) sw
+                                /*wildcard_hints = ((Integer) sw
                                         .getAttribute(IOFSwitch.PROP_FASTWILDCARDS))
                                         .intValue()
                                         & ~OFMatch.OFPFW_IN_PORT
@@ -281,12 +298,21 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
                                         & ~OFMatch.OFPFW_DL_SRC
                                         & ~OFMatch.OFPFW_DL_DST
                                         & ~OFMatch.OFPFW_NW_SRC_MASK
-                                        & ~OFMatch.OFPFW_NW_DST_MASK;
+                                        & ~OFMatch.OFPFW_NW_DST_MASK;*/
+                            	//TODO @Ryan does the use of NO_MASK here automatically assume isFullyWildcarded is true?
+                            	// dummy values set to not trigger isFullyWildcarded
+                            	wildcard_hints = sw.getOFFactory().buildMatch();
+                                wildcard_hints.setExact(MatchField.IN_PORT, OFPort.of(1));
+                                wildcard_hints.setExact(MatchField.VLAN_VID, OFVlanVidMatch.ofVlan(1));
+                                wildcard_hints.setExact(MatchField.ETH_SRC, MacAddress.BROADCAST);
+                                wildcard_hints.setExact(MatchField.ETH_DST, MacAddress.BROADCAST);
+                                wildcard_hints.setExact(MatchField.IPV4_SRC, IPv4Address.FULL_MASK);
+                                wildcard_hints.setExact(MatchField.IPV4_DST, IPv4Address.FULL_MASK);
                             }
 
                             pushRoute(route, match, wildcard_hints, pi, sw.getId(), cookie,
                                       cntx, requestFlowRemovedNotifn, false,
-                                      OFFlowMod.OFPFC_ADD);
+                                      OFFlowModCommand.ADD);
                         }
                     }
                     iSrcDaps++;
@@ -297,8 +323,9 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
                     iDstDaps++;
                 }
             }
+        // END DESTINATION DEVICE = KNOWN
         } else {
-            // Flood since we don't know the dst device
+        	// DESTINATION DEVICE = UNKNOWN, thus flood to hopefully/eventually find out where the destination is
             doFlood(sw, pi, cntx);
         }
     }
@@ -385,6 +412,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
         Collection<Class<? extends IFloodlightService>> l =
                 new ArrayList<Class<? extends IFloodlightService>>();
         l.add(IFloodlightProviderService.class);
+        l.add(IOFSwitchService.class);
         l.add(IDeviceService.class);
         l.add(IRoutingService.class);
         l.add(ITopologyService.class);
@@ -412,6 +440,7 @@ public class Forwarding extends ForwardingBase implements IFloodlightModule {
     public void init(FloodlightModuleContext context) throws FloodlightModuleException {
         super.init();
         this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+        this.switchService = context.getServiceImpl(IOFSwitchService.class);
         this.deviceManager = context.getServiceImpl(IDeviceService.class);
         this.routingEngine = context.getServiceImpl(IRoutingService.class);
         this.topology = context.getServiceImpl(ITopologyService.class);
diff --git a/src/main/java/net/floodlightcontroller/hub/Hub.java b/src/main/java/net/floodlightcontroller/hub/Hub.java
index 4a3549ba4..e683fa917 100644
--- a/src/main/java/net/floodlightcontroller/hub/Hub.java
+++ b/src/main/java/net/floodlightcontroller/hub/Hub.java
@@ -17,7 +17,6 @@
 
 package net.floodlightcontroller.hub;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -27,19 +26,20 @@ import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.LogicalOFMessageCategory;
 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 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.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
-import org.openflow.util.U16;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFPort;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -64,34 +64,24 @@ public class Hub implements IFloodlightModule, IOFMessageListener {
         return Hub.class.getPackage().getName();
     }
 
+    //TODO @Ryan this is a good example (my first try) at using the builders. Might be good reference later.
     public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
         OFPacketIn pi = (OFPacketIn) msg;
-        OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory()
-                .getMessage(OFType.PACKET_OUT);
-        po.setBufferId(pi.getBufferId())
-            .setInPort(pi.getInPort());
+        OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
+        pob.setBufferId(pi.getBufferId()).setInPort(pi.getInPort());
 
         // set actions
-        OFActionOutput action = new OFActionOutput()
-            .setPort(OFPort.OFPP_FLOOD.getValue());
-        po.setActions(Collections.singletonList((OFAction)action));
-        po.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH);
+        OFActionOutput.Builder actionBuilder = sw.getOFFactory().actions().buildOutput();
+            actionBuilder.setPort(OFPort.FLOOD);
+        pob.setActions(Collections.singletonList((OFAction) actionBuilder.build()));
+        // pob.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH); @Ryan setting of lengths is taken care of now, I think
 
         // set data if is is included in the packetin
-        if (pi.getBufferId() == OFPacketOut.BUFFER_ID_NONE) {
-            byte[] packetData = pi.getPacketData();
-            po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH
-                    + po.getActionsLength() + packetData.length));
-            po.setPacketData(packetData);
-        } else {
-            po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH
-                    + po.getActionsLength()));
-        }
-        try {
-            sw.write(po, cntx);
-        } catch (IOException e) {
-            log.error("Failure writing PacketOut", e);
+        if (pi.getBufferId() == OFBufferId.NO_BUFFER) {
+            byte[] packetData = pi.getData();
+            pob.setData(packetData);
         }
+        sw.write(pob.build(), LogicalOFMessageCategory.MAIN);
 
         return Command.CONTINUE;
     }
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java
index e4e109ca4..5025d8d69 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java
@@ -18,7 +18,9 @@ package net.floodlightcontroller.linkdiscovery;
 
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import org.openflow.util.HexString;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
 
 public interface ILinkDiscovery {
 
@@ -45,16 +47,16 @@ public interface ILinkDiscovery {
     }
 
     public class LDUpdate {
-        protected long src;
-        protected short srcPort;
-        protected long dst;
-        protected short dstPort;
+        protected DatapathId src;
+        protected OFPort srcPort;
+        protected DatapathId dst;
+        protected OFPort dstPort;
         protected SwitchType srcType;
         protected LinkType type;
         protected UpdateOperation operation;
 
-        public LDUpdate(long src, short srcPort,
-                      long dst, short dstPort,
+        public LDUpdate(DatapathId src, OFPort srcPort,
+        		DatapathId dst, OFPort dstPort,
                       ILinkDiscovery.LinkType type,
                       UpdateOperation operation) {
             this.src = src;
@@ -76,32 +78,32 @@ public interface ILinkDiscovery {
         }
 
         // For updtedSwitch(sw)
-        public LDUpdate(long switchId, SwitchType stype, UpdateOperation oper ){
+        public LDUpdate(DatapathId switchId, SwitchType stype, UpdateOperation oper ){
             this.operation = oper;
             this.src = switchId;
             this.srcType = stype;
         }
 
         // For port up or port down; and tunnel port added and removed.
-        public LDUpdate(long sw, short port, UpdateOperation operation) {
+        public LDUpdate(DatapathId sw, OFPort port, UpdateOperation operation) {
             this.src = sw;
             this.srcPort = port;
             this.operation = operation;
         }
 
-        public long getSrc() {
+        public DatapathId getSrc() {
             return src;
         }
 
-        public short getSrcPort() {
+        public OFPort getSrcPort() {
             return srcPort;
         }
 
-        public long getDst() {
+        public DatapathId getDst() {
             return dst;
         }
 
-        public short getDstPort() {
+        public OFPort getDstPort() {
             return dstPort;
         }
 
@@ -127,20 +129,20 @@ public interface ILinkDiscovery {
             case LINK_REMOVED:
             case LINK_UPDATED:
                 return "LDUpdate [operation=" + operation +
-                        ", src=" + HexString.toHexString(src)
-                        + ", srcPort=" + srcPort
-                        + ", dst=" + HexString.toHexString(dst) 
-                        + ", dstPort=" + dstPort
+                        ", src=" + src.toString()
+                        + ", srcPort=" + srcPort.toString()
+                        + ", dst=" + dst.toString()
+                        + ", dstPort=" + dstPort.toString()
                         + ", type=" + type + "]";
             case PORT_DOWN:
             case PORT_UP:
                 return "LDUpdate [operation=" + operation +
-                        ", src=" + HexString.toHexString(src)
-                        + ", srcPort=" + srcPort + "]";
+                        ", src=" + src.toString()
+                        + ", srcPort=" + srcPort.toString() + "]";
             case SWITCH_REMOVED:
             case SWITCH_UPDATED:
                 return "LDUpdate [operation=" + operation +
-                        ", src=" + HexString.toHexString(src) + "]";
+                        ", src=" + src.toString() + "]";
             default:
                 return "LDUpdate: Unknown update.";
             }
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java
index 3773efd71..2bb537279 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java
@@ -20,7 +20,10 @@ package net.floodlightcontroller.linkdiscovery;
 import java.util.Map;
 import java.util.Set;
 
-import org.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.OFPort;
 
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.routing.Link;
@@ -32,7 +35,7 @@ public interface ILinkDiscoveryService extends IFloodlightService {
     /**
      * Returns if a given switchport is a tunnel endpoint or not
      */
-    public boolean isTunnelPort(long sw, short port);
+    public boolean isTunnelPort(DatapathId sw, OFPort port);
 
     /**
      * Retrieves a map of all known link connections between OpenFlow switches
@@ -59,7 +62,7 @@ public interface ILinkDiscoveryService extends IFloodlightService {
      * to switchport (sw, port). PacketOut does not contain actions.
      * PacketOut length includes the minimum length and data length.
      */
-    public OFPacketOut generateLLDPMessage(long sw, short port,
+    public OFPacketOut generateLLDPMessage(DatapathId sw, OFPort port,
                                            boolean isStandard,
                                            boolean isReverse);
 
@@ -67,7 +70,7 @@ public interface ILinkDiscoveryService extends IFloodlightService {
      * Returns an unmodifiable map from switch id to a set of all links with it
      * as an endpoint.
      */
-    public Map<Long, Set<Link>> getSwitchLinks();
+    public Map<DatapathId, Set<Link>> getSwitchLinks();
 
     /**
      * Adds a listener to listen for ILinkDiscoveryService messages
@@ -84,17 +87,17 @@ public interface ILinkDiscoveryService extends IFloodlightService {
      * Adds a switch port to suppress lldp set. LLDPs and BDDPs will not be sent
      * out, and if any are received on this port then they will be dropped.
      */
-    public void AddToSuppressLLDPs(long sw, short port);
+    public void AddToSuppressLLDPs(DatapathId sw, OFPort port);
 
     /**
      * Removes a switch port from suppress lldp set
      */
-    public void RemoveFromSuppressLLDPs(long sw, short port);
+    public void RemoveFromSuppressLLDPs(DatapathId sw, OFPort port);
 
     /**
      * Get the set of quarantined ports on a switch
      */
-    public Set<Short> getQuarantinedPorts(long sw);
+    public Set<OFPort> getQuarantinedPorts(DatapathId sw);
 
     /**
      * Get the status of auto port fast feature.
@@ -126,5 +129,5 @@ public interface ILinkDiscoveryService extends IFloodlightService {
      *        ALL MAC addresses to the ignore list. This will cause a drop of
      *        ALL packet ins.
      */
-    public void addMACToIgnoreList(long mac, int ignoreBits);
+    public void addMACToIgnoreList(MacAddress mac, int ignoreBits);
 }
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java b/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java
index 0230b3bbd..6c2d7334e 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java
@@ -15,15 +15,17 @@
 
 package net.floodlightcontroller.linkdiscovery;
 
+import java.util.Date;
+
 import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LinkType;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 
 public class LinkInfo {
 
-    public LinkInfo(Long firstSeenTime,
-                    Long lastLldpReceivedTime,
-                    Long lastBddpReceivedTime) {
+    public LinkInfo(Date firstSeenTime,
+                    Date lastLldpReceivedTime,
+                    Date lastBddpReceivedTime) {
         super();
         this.firstSeenTime = firstSeenTime;
         this.lastLldpReceivedTime = lastLldpReceivedTime;
@@ -46,9 +48,9 @@ public class LinkInfo {
         this.lastBddpReceivedTime = fromLinkInfo.getMulticastValidTime();
     }
 
-    protected Long firstSeenTime;
-    protected Long lastLldpReceivedTime; /* Standard LLLDP received time */
-    protected Long lastBddpReceivedTime; /* Modified LLDP received time  */
+    protected Date firstSeenTime;
+    protected Date lastLldpReceivedTime; /* Standard LLLDP received time */
+    protected Date lastBddpReceivedTime; /* Modified LLDP received time  */
 
     /** The port states stored here are topology's last knowledge of
      * the state of the port. This mostly mirrors the state
@@ -60,27 +62,27 @@ public class LinkInfo {
      * requires the new state to be written to storage.
      */
 
-    public Long getFirstSeenTime() {
+    public Date getFirstSeenTime() {
         return firstSeenTime;
     }
 
-    public void setFirstSeenTime(Long firstSeenTime) {
+    public void setFirstSeenTime(Date firstSeenTime) {
         this.firstSeenTime = firstSeenTime;
     }
 
-    public Long getUnicastValidTime() {
+    public Date getUnicastValidTime() {
         return lastLldpReceivedTime;
     }
 
-    public void setUnicastValidTime(Long unicastValidTime) {
+    public void setUnicastValidTime(Date unicastValidTime) {
         this.lastLldpReceivedTime = unicastValidTime;
     }
 
-    public Long getMulticastValidTime() {
+    public Date getMulticastValidTime() {
         return lastBddpReceivedTime;
     }
 
-    public void setMulticastValidTime(Long multicastValidTime) {
+    public void setMulticastValidTime(Date multicastValidTime) {
         this.lastBddpReceivedTime = multicastValidTime;
     }
 
@@ -147,8 +149,8 @@ public class LinkInfo {
      */
     @Override
     public String toString() {
-        return "LinkInfo [unicastValidTime=" + ((lastLldpReceivedTime == null) ? "null" : lastLldpReceivedTime)
-                + ", multicastValidTime=" + ((lastBddpReceivedTime == null) ? "null" : lastBddpReceivedTime)
+        return "LinkInfo [unicastValidTime=" + ((lastLldpReceivedTime == null) ? "null" : lastLldpReceivedTime.getTime())
+                + ", multicastValidTime=" + ((lastBddpReceivedTime == null) ? "null" : lastBddpReceivedTime.getTime())
                 + "]";
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java b/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java
index c9115eacb..63f710e58 100644
--- a/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java
+++ b/src/main/java/net/floodlightcontroller/packet/BSNPROBE.java
@@ -21,7 +21,7 @@ package net.floodlightcontroller.packet;
 
 import java.nio.ByteBuffer;
 import java.util.Arrays;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.util.HexString;
 
 /**
  * @author Shudong Zhou (shudong.zhou@bigswitch.com)
diff --git a/src/main/java/net/floodlightcontroller/packet/Ethernet.java b/src/main/java/net/floodlightcontroller/packet/Ethernet.java
index 60887b315..d29b0859c 100644
--- a/src/main/java/net/floodlightcontroller/packet/Ethernet.java
+++ b/src/main/java/net/floodlightcontroller/packet/Ethernet.java
@@ -22,8 +22,8 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 
-import net.floodlightcontroller.util.MACAddress;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.util.HexString;
 
 /**
  *
@@ -49,8 +49,8 @@ public class Ethernet extends BasePacket {
         etherTypeClassMap.put(TYPE_BSN, BSN.class);
     }
 
-    protected MACAddress destinationMACAddress;
-    protected MACAddress sourceMACAddress;
+    protected MacAddress destinationMACAddress;
+    protected MacAddress sourceMACAddress;
     protected byte priorityCode;
     protected short vlanID;
     protected short etherType;
@@ -68,13 +68,13 @@ public class Ethernet extends BasePacket {
      * @return the destination MAC as a byte array
      */
     public byte[] getDestinationMACAddress() {
-        return destinationMACAddress.toBytes();
+        return destinationMACAddress.getBytes();
     }
     
     /**
      * @return the destination MAC
      */
-    public MACAddress getDestinationMAC() {
+    public MacAddress getDestinationMAC() {
         return destinationMACAddress;
     }
 
@@ -82,7 +82,7 @@ public class Ethernet extends BasePacket {
      * @param destinationMACAddress the destination MAC to set
      */
     public Ethernet setDestinationMACAddress(byte[] destinationMACAddress) {
-        this.destinationMACAddress = MACAddress.valueOf(destinationMACAddress);
+        this.destinationMACAddress = MacAddress.of(destinationMACAddress);
         return this;
     }
 
@@ -90,7 +90,7 @@ public class Ethernet extends BasePacket {
      * @param destinationMACAddress the destination MAC to set
      */
     public Ethernet setDestinationMACAddress(String destinationMACAddress) {
-        this.destinationMACAddress = MACAddress.valueOf(destinationMACAddress);
+        this.destinationMACAddress = MacAddress.of(destinationMACAddress);
         return this;
     }
 
@@ -98,13 +98,13 @@ public class Ethernet extends BasePacket {
      * @return the source MACAddress as a byte array
      */
     public byte[] getSourceMACAddress() {
-        return sourceMACAddress.toBytes();
+        return sourceMACAddress.getBytes();
     }
     
     /**
      * @return the source MACAddress
      */
-    public MACAddress getSourceMAC() {
+    public MacAddress getSourceMAC() {
         return sourceMACAddress;
     }
 
@@ -112,7 +112,7 @@ public class Ethernet extends BasePacket {
      * @param sourceMACAddress the source MAC to set
      */
     public Ethernet setSourceMACAddress(byte[] sourceMACAddress) {
-        this.sourceMACAddress = MACAddress.valueOf(sourceMACAddress);
+        this.sourceMACAddress = MacAddress.of(sourceMACAddress);
         return this;
     }
 
@@ -120,7 +120,7 @@ public class Ethernet extends BasePacket {
      * @param sourceMACAddress the source MAC to set
      */
     public Ethernet setSourceMACAddress(String sourceMACAddress) {
-        this.sourceMACAddress = MACAddress.valueOf(sourceMACAddress);
+        this.sourceMACAddress = MacAddress.of(sourceMACAddress);
         return this;
     }
 
@@ -173,7 +173,7 @@ public class Ethernet extends BasePacket {
      * @return True if the Ethernet frame is broadcast, false otherwise
      */
     public boolean isBroadcast() {
-        assert(destinationMACAddress.length() == 6);
+        assert(destinationMACAddress.getLength() == 6);
         return destinationMACAddress.isBroadcast();
     }
     
@@ -213,8 +213,8 @@ public class Ethernet extends BasePacket {
         }
         byte[] data = new byte[length];
         ByteBuffer bb = ByteBuffer.wrap(data);
-        bb.put(destinationMACAddress.toBytes());
-        bb.put(sourceMACAddress.toBytes());
+        bb.put(destinationMACAddress.getBytes());
+        bb.put(sourceMACAddress.getBytes());
         if (vlanID != VLAN_UNTAGGED) {
             bb.putShort((short) 0x8100);
             bb.putShort((short) ((priorityCode << 13) | (vlanID & 0x0fff)));
@@ -234,16 +234,16 @@ public class Ethernet extends BasePacket {
             return null;
         ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
         if (this.destinationMACAddress == null)
-            this.destinationMACAddress = MACAddress.valueOf(new byte[6]);
-        byte[] dstAddr = new byte[MACAddress.MAC_ADDRESS_LENGTH];
+            this.destinationMACAddress = MacAddress.of(new byte[6]);
+        byte[] dstAddr = new byte[MacAddress.NONE.getLength()];
         bb.get(dstAddr);
-        this.destinationMACAddress = MACAddress.valueOf(dstAddr);
+        this.destinationMACAddress = MacAddress.of(dstAddr);
 
         if (this.sourceMACAddress == null)
-            this.sourceMACAddress = MACAddress.valueOf(new byte[6]);
-        byte[] srcAddr = new byte[MACAddress.MAC_ADDRESS_LENGTH];
+            this.sourceMACAddress = MacAddress.of(new byte[6]);
+        byte[] srcAddr = new byte[MacAddress.NONE.getLength()];
         bb.get(srcAddr);
-        this.sourceMACAddress = MACAddress.valueOf(srcAddr);
+        this.sourceMACAddress = MacAddress.of(srcAddr);
 
         short etherType = bb.getShort();
         if (etherType == (short) 0x8100) {
@@ -322,7 +322,7 @@ public class Ethernet extends BasePacket {
      * @return The macAddress as a byte array 
      */
     public static byte[] toMACAddress(String macAddress) {
-        return MACAddress.valueOf(macAddress).toBytes();
+        return MacAddress.of(macAddress).getBytes();
     }
 
 
@@ -333,7 +333,7 @@ public class Ethernet extends BasePacket {
      * @return a long containing the mac address bytes
      */
     public static long toLong(byte[] macAddress) {
-        return MACAddress.valueOf(macAddress).toLong();
+        return MacAddress.of(macAddress).getLong();
     }
 
     /**
@@ -342,7 +342,7 @@ public class Ethernet extends BasePacket {
      * @return the bytes of the mac address
      */
     public static byte[] toByteArray(long macAddress) {
-        return MACAddress.valueOf(macAddress).toBytes();
+        return MacAddress.of(macAddress).getBytes();
     }
     
     /* (non-Javadoc)
diff --git a/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java b/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java
index cc70487eb..0198d16a4 100644
--- a/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java
+++ b/src/main/java/net/floodlightcontroller/perfmon/IPktInProcessingTimeService.java
@@ -18,7 +18,7 @@ package net.floodlightcontroller.perfmon;
 
 import java.util.List;
 
-import org.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFMessage;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IOFMessageListener;
diff --git a/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java
index 51641ccc7..c10bc93a6 100644
--- a/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java
+++ b/src/main/java/net/floodlightcontroller/perfmon/NullPktInProcessingTime.java
@@ -22,7 +22,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFMessage;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IOFMessageListener;
diff --git a/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java
index 366721120..9e754469d 100644
--- a/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java
+++ b/src/main/java/net/floodlightcontroller/perfmon/PktInProcessingTime.java
@@ -37,8 +37,8 @@ import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.restserver.IRestApiService;
 
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/routing/BroadcastTree.java b/src/main/java/net/floodlightcontroller/routing/BroadcastTree.java
index 0c3703c97..28ca79f84 100644
--- a/src/main/java/net/floodlightcontroller/routing/BroadcastTree.java
+++ b/src/main/java/net/floodlightcontroller/routing/BroadcastTree.java
@@ -20,48 +20,48 @@ import java.util.HashMap;
 
 import net.floodlightcontroller.routing.Link;
 
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.types.DatapathId;
 
 public class BroadcastTree {
-    protected HashMap<Long, Link> links;
-    protected HashMap<Long, Integer> costs;
+    protected HashMap<DatapathId, Link> links;
+    protected HashMap<DatapathId, Integer> costs;
 
     public BroadcastTree() {
-        links = new HashMap<Long, Link>();
-        costs = new HashMap<Long, Integer>();
+        links = new HashMap<DatapathId, Link>();
+        costs = new HashMap<DatapathId, Integer>();
     }
 
-    public BroadcastTree(HashMap<Long, Link> links, HashMap<Long, Integer> costs) {
+    public BroadcastTree(HashMap<DatapathId, Link> links, HashMap<DatapathId, Integer> costs) {
         this.links = links;
         this.costs = costs;
     }
 
-    public Link getTreeLink(long node) {
+    public Link getTreeLink(DatapathId node) {
         return links.get(node);
     }
 
-    public int getCost(long node) {
+    public int getCost(DatapathId node) {
         if (costs.get(node) == null) return -1;
         return (costs.get(node));
     }
 
-    public HashMap<Long, Link> getLinks() {
+    public HashMap<DatapathId, Link> getLinks() {
         return links;
     }
 
-    public void addTreeLink(long myNode, Link link) {
+    public void addTreeLink(DatapathId myNode, Link link) {
         links.put(myNode, link);
     }
 
     public String toString() {
         StringBuffer sb = new StringBuffer();
-        for(long n: links.keySet()) {
-            sb.append("[" + HexString.toHexString(n) + ": cost=" + costs.get(n) + ", " + links.get(n) + "]");
+        for(DatapathId n: links.keySet()) {
+            sb.append("[" + n.toString() + ": cost=" + costs.get(n) + ", " + links.get(n) + "]");
         }
         return sb.toString();
     }
 
-    public HashMap<Long, Integer> getCosts() {
+    public HashMap<DatapathId, Integer> getCosts() {
         return costs;
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
index 2ef42197b..a3b225514 100644
--- a/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
+++ b/src/main/java/net/floodlightcontroller/routing/ForwardingBase.java
@@ -32,6 +32,7 @@ import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.annotations.LogMessageCategory;
 import net.floodlightcontroller.core.annotations.LogMessageDoc;
 import net.floodlightcontroller.core.annotations.LogMessageDocs;
+import net.floodlightcontroller.core.internal.IOFSwitchService;
 import net.floodlightcontroller.core.util.AppCookie;
 import net.floodlightcontroller.counter.ICounterStoreService;
 import net.floodlightcontroller.devicemanager.IDeviceService;
@@ -46,14 +47,26 @@ import net.floodlightcontroller.topology.NodePortTuple;
 import net.floodlightcontroller.util.OFMessageDamper;
 import net.floodlightcontroller.util.TimedCache;
 
-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.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.protocol.match.MatchFields;
+import org.projectfloodlight.openflow.protocol.OFFlowAdd;
+import org.projectfloodlight.openflow.protocol.OFFlowModCommand;
+import org.projectfloodlight.openflow.protocol.OFFlowModify;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.OFPacketQueue;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFUint64;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -83,6 +96,7 @@ public abstract class ForwardingBase
     protected IRoutingService routingEngine;
     protected ITopologyService topology;
     protected ICounterStoreService counterStore;
+    protected IOFSwitchService switchService;
 
     protected OFMessageDamper messageDamper;
 
@@ -106,9 +120,9 @@ public abstract class ForwardingBase
             new Comparator<SwitchPort>() {
                 @Override
                 public int compare(SwitchPort d1, SwitchPort d2) {
-                    Long d1ClusterId =
+                    DatapathId d1ClusterId =
                             topology.getL2DomainId(d1.getSwitchDPID());
-                    Long d2ClusterId =
+                    DatapathId d2ClusterId =
                             topology.getL2DomainId(d2.getSwitchDPID());
                     return d1ClusterId.compareTo(d2ClusterId);
                 }
@@ -204,40 +218,35 @@ public abstract class ForwardingBase
                         "flow modification to a switch",
             recommendation=LogMessageDoc.CHECK_SWITCH)
     })
-    public boolean pushRoute(Route route, OFMatch match,
-                             Integer wildcard_hints,
+    public boolean pushRoute(Route route, Match match,
+                             Match.Builder wildcard_hints,
                              OFPacketIn pi,
-                             long pinSwitch,
+                             DatapathId pinSwitch,
                              long cookie,
                              FloodlightContext cntx,
                              boolean reqeustFlowRemovedNotifn,
                              boolean doFlush,
-                             short   flowModCommand) {
+                             OFFlowModCommand flowModCommand) {
 
         boolean srcSwitchIncluded = false;
-        OFFlowMod fm =
-                (OFFlowMod) floodlightProvider.getOFMessageFactory()
-                                              .getMessage(OFType.FLOW_MOD);
-        OFActionOutput action = new OFActionOutput();
-        action.setMaxLength((short)0xffff);
+        OFFlowAdd.Builder fmb = switchService.getSwitch(pinSwitch).getOFFactory().buildFlowAdd();
+        OFActionOutput.Builder actionOutputBuilder = switchService.getSwitch(pinSwitch).getOFFactory().actions().buildOutput();
+        actionOutputBuilder.setMaxLen((int) 0xffffffff);
         List<OFAction> actions = new ArrayList<OFAction>();
-        actions.add(action);
-
-        fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
-            .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
-            .setBufferId(OFPacketOut.BUFFER_ID_NONE)
-            .setCookie(cookie)
-            .setCommand(flowModCommand)
-            .setMatch(match)
-            .setActions(actions)
-            .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
-
+        actions.add(actionOutputBuilder.build());
+
+        fmb.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
+        .setHardTimeout(FLOWMOD_DEFAULT_HARD_TIMEOUT)
+        .setBufferId(OFBufferId.NO_BUFFER)
+        .setCookie(U64.of(cookie))
+        .setMatch(match)
+        .setActions(actions);
         List<NodePortTuple> switchPortList = route.getPath();
 
-        for (int indx = switchPortList.size()-1; indx > 0; indx -= 2) {
+        for (int indx = switchPortList.size() - 1; indx > 0; indx -= 2) {
             // indx and indx-1 will always have the same switch DPID.
-            long switchDPID = switchPortList.get(indx).getNodeId();
-            IOFSwitch sw = floodlightProvider.getSwitch(switchDPID);
+            DatapathId switchDPID = switchPortList.get(indx).getNodeId();
+            IOFSwitch sw = switchService.getSwitch(switchDPID);
             if (sw == null) {
                 if (log.isWarnEnabled()) {
                     log.warn("Unable to push route, switch at DPID {} " +
@@ -247,26 +256,29 @@ public abstract class ForwardingBase
             }
 
             // set the match.
-            fm.setMatch(wildcard(match, sw, wildcard_hints));
+            fmb.setMatch(wildcard(match, sw, wildcard_hints));
 
             // set buffer id if it is the source switch
-            if (1 == indx) {
+            // this only appears to set wildcards, which I think are not necessary
+            /*if (1 == indx) {
                 // Set the flag to request flow-mod removal notifications only for the
                 // source switch. The removal message is used to maintain the flow
                 // cache. Don't set the flag for ARP messages - TODO generalize check
                 if ((reqeustFlowRemovedNotifn)
-                        && (match.getDataLayerType() != Ethernet.TYPE_ARP)) {
-                    /**with new flow cache design, we don't need the flow removal message from switch anymore
-                    fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
-                    */
-                    match.setWildcards(fm.getMatch().getWildcards());
+                        && (match.get(MatchField.ARP_OP).getOpcode() != Ethernet.TYPE_ARP)) {
+                    //with new flow cache design, we don't need the flow removal message from switch anymore
+                    //fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
+                    //
+                    match.setWildcards(fmb.getMatch().getWildcards());
                 }
-            }
+            }*/
 
-            short outPort = switchPortList.get(indx).getPortId();
-            short inPort = switchPortList.get(indx-1).getPortId();
+            OFPort outPort = switchPortList.get(indx).getPortId();
+            OFPort inPort = switchPortList.get(indx-1).getPortId();
             // set input and output ports on the switch
-            fm.getMatch().setInputPort(inPort);
+            Match m = fmb.getMatch();
+            m.
+            .setInputPort(inPort);
             ((OFActionOutput)fm.getActions().get(0)).setPort(outPort);
 
             try {
@@ -286,7 +298,7 @@ public abstract class ForwardingBase
                 }
 
                 // Push the packet out the source switch
-                if (sw.getId() == pinSwitch) {
+                if (sw.getId().equals(pinSwitch)) {
                     // TODO: Instead of doing a packetOut here we could also
                     // send a flowMod with bufferId set....
                     pushPacket(sw, pi, false, outPort, cntx);
@@ -306,13 +318,13 @@ public abstract class ForwardingBase
         return srcSwitchIncluded;
     }
 
-    protected OFMatch wildcard(OFMatch match, IOFSwitch sw,
+    /*protected Match wildcard(Match match, IOFSwitch sw,
                                Integer wildcard_hints) {
         if (wildcard_hints != null) {
             return match.clone().setWildcards(wildcard_hints.intValue());
         }
         return match.clone();
-    }
+    }*/
 
     /**
      * Pushes a packet-out to a switch. If bufferId != BUFFER_ID_NONE we
@@ -357,7 +369,7 @@ public abstract class ForwardingBase
      */
     protected void pushPacket(IOFSwitch sw, OFPacketIn pi,
                            boolean useBufferId,
-                           short outport, FloodlightContext cntx) {
+                           OFPort outport, FloodlightContext cntx) {
 
         if (pi == null) {
             return;
@@ -381,37 +393,35 @@ public abstract class ForwardingBase
                       new Object[] {sw, pi});
         }
 
-        OFPacketOut po =
-                (OFPacketOut) floodlightProvider.getOFMessageFactory()
-                                                .getMessage(OFType.PACKET_OUT);
+        //OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT);
+        OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
 
         // set actions
         List<OFAction> actions = new ArrayList<OFAction>();
-        actions.add(new OFActionOutput(outport, (short) 0xffff));
+        //actions.add(new OFActionOutput(outport, (short) 0xffff));
+        actions.add(sw.getOFFactory().actions().output(outport, (int) 0xffffffff));
 
-        po.setActions(actions)
-          .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH);
-        short poLength =
-                (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH);
+        pob.setActions(actions);
+          //.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH);
+        //short poLength = (short) (po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH);
 
         if (useBufferId) {
-            po.setBufferId(pi.getBufferId());
+            pob.setBufferId(pi.getBufferId());
         } else {
-            po.setBufferId(OFPacketOut.BUFFER_ID_NONE);
+            pob.setBufferId(OFBufferId.NO_BUFFER);
         }
 
-        if (po.getBufferId() == OFPacketOut.BUFFER_ID_NONE) {
-            byte[] packetData = pi.getPacketData();
-            poLength += packetData.length;
-            po.setPacketData(packetData);
+        if (pob.getBufferId() == OFBufferId.NO_BUFFER) {
+            //poLength += packetData.length;
+            pob.setData(pi.getData());
         }
 
-        po.setInPort(pi.getInPort());
-        po.setLength(poLength);
+        pob.setInPort(pi.getInPort());
+        //po.setLength(poLength);
 
         try {
-            counterStore.updatePktOutFMCounterStoreLocal(sw, po);
-            messageDamper.write(sw, po, cntx);
+            counterStore.updatePktOutFMCounterStoreLocal(sw, pob.build());
+            messageDamper.write(sw, pob.build(), cntx);
         } catch (IOException e) {
             log.error("Failure writing packet out", e);
         }
@@ -429,46 +439,43 @@ public abstract class ForwardingBase
      */
     public void packetOutMultiPort(byte[] packetData,
                                    IOFSwitch sw,
-                                   short inPort,
-                                   Set<Integer> outPorts,
+                                   OFPort inPort,
+                                   Set<OFPort> outPorts,
                                    FloodlightContext cntx) {
         //setting actions
         List<OFAction> actions = new ArrayList<OFAction>();
 
-        Iterator<Integer> j = outPorts.iterator();
+        Iterator<OFPort> j = outPorts.iterator();
 
         while (j.hasNext())
         {
-            actions.add(new OFActionOutput(j.next().shortValue(),
-                                           (short) 0));
+            //actions.add(new OFActionOutput(j.next().shortValue(), (short) 0));
+            actions.add(sw.getOFFactory().actions().output(j.next(), 0));
         }
 
-        OFPacketOut po =
-                (OFPacketOut) floodlightProvider.getOFMessageFactory().
-                getMessage(OFType.PACKET_OUT);
-        po.setActions(actions);
-        po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH *
-                outPorts.size()));
+        //OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT);
+        OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
+        pob.setActions(actions);
+        //po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * outPorts.size()));
 
         // set buffer-id to BUFFER_ID_NONE, and set in-port to OFPP_NONE
-        po.setBufferId(OFPacketOut.BUFFER_ID_NONE);
-        po.setInPort(inPort);
+        pob.setBufferId(OFBufferId.NO_BUFFER);
+        pob.setInPort(inPort);
 
         // data (note buffer_id is always BUFFER_ID_NONE) and length
-        short poLength = (short)(po.getActionsLength() +
-                OFPacketOut.MINIMUM_LENGTH);
-        poLength += packetData.length;
-        po.setPacketData(packetData);
-        po.setLength(poLength);
+        //short poLength = (short)(po.getActionsLength() + OFPacketOut.MINIMUM_LENGTH);
+        //poLength += packetData.length;
+        pob.setData(packetData);
+        //po.setLength(poLength);
 
         try {
-            counterStore.updatePktOutFMCounterStoreLocal(sw, po);
+            counterStore.updatePktOutFMCounterStoreLocal(sw, pob.build());
             if (log.isTraceEnabled()) {
                 log.trace("write broadcast packet on switch-id={} " +
                         "interfaces={} packet-out={}",
-                        new Object[] {sw.getId(), outPorts, po});
+                        new Object[] {sw.getId(), outPorts, pob.build()});
             }
-            messageDamper.write(sw, po, cntx);
+            messageDamper.write(sw, pob.build(), cntx);
 
         } catch (IOException e) {
             log.error("Failure writing packet out", e);
@@ -482,10 +489,10 @@ public abstract class ForwardingBase
      */
     public void packetOutMultiPort(OFPacketIn pi,
                                    IOFSwitch sw,
-                                   short inPort,
-                                   Set<Integer> outPorts,
+                                   OFPort inPort,
+                                   Set<OFPort> outPorts,
                                    FloodlightContext cntx) {
-        packetOutMultiPort(pi.getPacketData(), sw, inPort, outPorts, cntx);
+        packetOutMultiPort(pi.getData(), sw, inPort, outPorts, cntx);
     }
 
     /**
@@ -495,8 +502,8 @@ public abstract class ForwardingBase
      */
     public void packetOutMultiPort(IPacket packet,
                                    IOFSwitch sw,
-                                   short inPort,
-                                   Set<Integer> outPorts,
+                                   OFPort inPort,
+                                   Set<OFPort> outPorts,
                                    FloodlightContext cntx) {
         packetOutMultiPort(packet.serialize(), sw, inPort, outPorts, cntx);
     }
@@ -515,8 +522,8 @@ public abstract class ForwardingBase
                 IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
 
         Long broadcastHash;
-        broadcastHash = topology.getL2DomainId(sw.getId()) * prime1 +
-                        pi.getInPort() * prime2 + eth.hashCode();
+        broadcastHash = topology.getL2DomainId(sw.getId()).getLong() * prime1 +
+                        pi.getInPort().getPortNumber() * prime2 + eth.hashCode();
         if (broadcastCache.update(broadcastHash)) {
             sw.updateBroadcastCache(broadcastHash, pi.getInPort());
             return true;
@@ -535,7 +542,7 @@ public abstract class ForwardingBase
         Ethernet eth =
                 IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
 
-        long hash =  pi.getInPort() * prime2 + eth.hashCode();
+        long hash =  pi.getInPort().getPortNumber() * prime2 + eth.hashCode();
 
         // some FORWARD_OR_FLOOD packets are unicast with unknown destination mac
         return sw.updateBroadcastCache(hash, pi.getInPort());
@@ -549,53 +556,43 @@ public abstract class ForwardingBase
             recommendation=LogMessageDoc.CHECK_SWITCH)
     })
     public static boolean
-            blockHost(IFloodlightProviderService floodlightProvider,
-                      SwitchPort sw_tup, long host_mac,
+            blockHost(IOFSwitchService switchService,
+                      SwitchPort sw_tup, MacAddress host_mac,
                       short hardTimeout, long cookie) {
 
         if (sw_tup == null) {
             return false;
         }
 
-        IOFSwitch sw =
-                floodlightProvider.getSwitch(sw_tup.getSwitchDPID());
+        IOFSwitch sw = switchService.getSwitch(sw_tup.getSwitchDPID());
         if (sw == null) return false;
-        int inputPort = sw_tup.getPort();
+        OFPort inputPort = sw_tup.getPort();
         log.debug("blockHost sw={} port={} mac={}",
-                  new Object[] { sw, sw_tup.getPort(), Long.valueOf(host_mac) });
+                  new Object[] { sw, sw_tup.getPort(), host_mac.getLong() });
 
         // Create flow-mod based on packet-in and src-switch
-        OFFlowMod fm =
-                (OFFlowMod) floodlightProvider.getOFMessageFactory()
-                                              .getMessage(OFType.FLOW_MOD);
-        OFMatch match = new OFMatch();
+        OFFlowMod.Builder fmb = switchService.getSwitch(sw_tup.getSwitchDPID()).getOFFactory().buildFlowAdd();
+        Match.Builder mb = switchService.getSwitch(sw_tup.getSwitchDPID()).getOFFactory().buildMatch();
         List<OFAction> actions = new ArrayList<OFAction>(); // Set no action to
                                                             // drop
-        match.setInputPort((short)inputPort);
-        if (host_mac != -1L) {
-            match.setDataLayerSource(Ethernet.toByteArray(host_mac))
-                .setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_DL_SRC
-                               & ~OFMatch.OFPFW_IN_PORT);
-        } else {
+        mb.setExact(MatchField.IN_PORT, inputPort);
+        if (host_mac.getLong() != -1L) {
+            //match.setDataLayerSource(Ethernet.toByteArray(host_mac)).setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_IN_PORT);
+            mb.setExact(MatchField.ETH_SRC, host_mac);
+        } /*else {
             match.setWildcards(OFMatch.OFPFW_ALL & ~OFMatch.OFPFW_IN_PORT);
-        }
-        fm.setCookie(cookie)
+        }*/
+        fmb.setCookie(U64.of(cookie))
           .setHardTimeout(hardTimeout)
           .setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
-          .setBufferId(OFPacketOut.BUFFER_ID_NONE)
-          .setMatch(match)
-          .setActions(actions)
-          .setLengthU(OFFlowMod.MINIMUM_LENGTH); // +OFActionOutput.MINIMUM_LENGTH);
-
-        try {
-            log.debug("write drop flow-mod sw={} match={} flow-mod={}",
-                      new Object[] { sw, match, fm });
-            // TODO: can't use the message damper sine this method is static
-            sw.write(fm, null);
-        } catch (IOException e) {
-            log.error("Failure writing deny flow mod", e);
-            return false;
-        }
+          .setBufferId(OFBufferId.NO_BUFFER)
+          .setMatch(mb.build())
+          .setActions(actions);
+
+        log.debug("write drop flow-mod sw={} match={} flow-mod={}",
+		          new Object[] { sw, mb.build(), fmb.build() });
+		// TODO: can't use the message damper sine this method is static
+		sw.write(fmb.build(), null);
         return true;
 
     }
diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java b/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java
index ab0937548..9c7a28597 100644
--- a/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java
+++ b/src/main/java/net/floodlightcontroller/routing/IRoutingDecision.java
@@ -19,6 +19,8 @@ package net.floodlightcontroller.routing;
 
 import java.util.List;
 
+import org.projectfloodlight.openflow.protocol.match.Match;
+
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.FloodlightContextStore;
 import net.floodlightcontroller.devicemanager.IDevice;
@@ -57,8 +59,8 @@ public interface IRoutingDecision {
     public void addDestinationDevice(IDevice d);
     public List<SwitchPort> getMulticastInterfaces();
     public void setMulticastInterfaces(List<SwitchPort> lspt);
-    public Integer getWildcards();
-    public void setWildcards(Integer wildcards);
+    public Match.Builder getWildcards();
+    public void setWildcards(Match.Builder wildcards);
     public short getHardTimeout();
     public void setHardTimeout(short hardTimeout);
 }
diff --git a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
index a3d77a83b..6cff6f533 100644
--- a/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
+++ b/src/main/java/net/floodlightcontroller/routing/IRoutingService.java
@@ -19,6 +19,9 @@ package net.floodlightcontroller.routing;
 
 import java.util.ArrayList;
 
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.routing.Route;
 
@@ -33,7 +36,7 @@ public interface IRoutingService extends IFloodlightService {
      * @param dst Destination switch DPID.
      * @param cookie cookie (usage determined by implementation; ignored by topology instance now).
      */
-    public Route getRoute(long src, long dst, long cookie);
+    public Route getRoute(DatapathId src, DatapathId dst, long cookie);
 
     /**
      * Provides a route between src and dst, with option to allow or
@@ -43,7 +46,7 @@ public interface IRoutingService extends IFloodlightService {
      * @param cookie cookie (usage determined by implementation; ignored by topology instance now).
      * @param tunnelEnabled boolean option.
      */
-    public Route getRoute(long src, long dst, long cookie, boolean tunnelEnabled);
+    public Route getRoute(DatapathId src, DatapathId dst, long cookie, boolean tunnelEnabled);
 
     /**
      * Provides a route between srcPort on src and dstPort on dst.
@@ -53,8 +56,8 @@ public interface IRoutingService extends IFloodlightService {
      * @param dstPort dstPort on Destination switch.
      * @param cookie cookie (usage determined by implementation; ignored by topology instance now).
      */
-    public Route getRoute(long srcId, short srcPort,
-                             long dstId, short dstPort, long cookie);
+    public Route getRoute(DatapathId srcId, OFPort srcPort,
+    		DatapathId dstId, OFPort dstPort, long cookie);
 
     /**
      * Provides a route between srcPort on src and dstPort on dst.
@@ -65,21 +68,21 @@ public interface IRoutingService extends IFloodlightService {
      * @param cookie cookie (usage determined by implementation; ignored by topology instance now).
      * @param tunnelEnabled boolean option.
      */
-    public Route getRoute(long srcId, short srcPort,
-                             long dstId, short dstPort, long cookie,
+    public Route getRoute(DatapathId srcId, OFPort srcPort,
+    		DatapathId dstId, OFPort dstPort, long cookie,
                              boolean tunnelEnabled);
 
     /** return all routes, if available */
-    public ArrayList<Route> getRoutes(long longSrcDpid, long longDstDpid, boolean tunnelEnabled);
+    public ArrayList<Route> getRoutes(DatapathId longSrcDpid, DatapathId longDstDpid, boolean tunnelEnabled);
 
     /** Check if a route exists between src and dst, including tunnel links
      *  in the path.
      */
-    public boolean routeExists(long src, long dst);
+    public boolean routeExists(DatapathId src, DatapathId dst);
 
     /** Check if a route exists between src and dst, with option to have
      *  or not have tunnels as part of the path.
      */
-    public boolean routeExists(long src, long dst, boolean tunnelEnabled);
+    public boolean routeExists(DatapathId src, DatapathId dst, boolean tunnelEnabled);
 
 }
diff --git a/src/main/java/net/floodlightcontroller/routing/Link.java b/src/main/java/net/floodlightcontroller/routing/Link.java
index 561ae04c0..a2f125f5a 100755
--- a/src/main/java/net/floodlightcontroller/routing/Link.java
+++ b/src/main/java/net/floodlightcontroller/routing/Link.java
@@ -18,34 +18,28 @@
 package net.floodlightcontroller.routing;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import org.openflow.util.HexString;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
 
 public class Link implements Comparable<Link> {
     @JsonProperty("src-switch")
-    private long src;
+    private DatapathId src;
     @JsonProperty("src-port")
-    private short srcPort;
+    private OFPort srcPort;
     @JsonProperty("dst-switch")
-    private long dst;
+    private DatapathId dst;
     @JsonProperty("dst-port")
-    private short dstPort;
+    private OFPort dstPort;
 
 
-    public Link(long srcId, short srcPort, long dstId, short dstPort) {
+    public Link(DatapathId srcId, OFPort srcPort, DatapathId dstId, OFPort dstPort) {
         this.src = srcId;
         this.srcPort = srcPort;
         this.dst = dstId;
         this.dstPort = dstPort;
     }
 
-    // Convenience method
-    public Link(long srcId, int srcPort, long dstId, int dstPort) {
-        this.src = srcId;
-        this.srcPort = (short) srcPort;
-        this.dst = dstId;
-        this.dstPort = (short) dstPort;
-    }
-
     /*
      * Do not use this constructor. Used primarily for JSON
      * Serialization/Deserialization
@@ -54,35 +48,35 @@ public class Link implements Comparable<Link> {
         super();
     }
 
-    public long getSrc() {
+    public DatapathId getSrc() {
         return src;
     }
 
-    public short getSrcPort() {
+    public OFPort getSrcPort() {
         return srcPort;
     }
 
-    public long getDst() {
+    public DatapathId getDst() {
         return dst;
     }
 
-    public short getDstPort() {
+    public OFPort getDstPort() {
         return dstPort;
     }
 
-    public void setSrc(long src) {
+    public void setSrc(DatapathId src) {
         this.src = src;
     }
 
-    public void setSrcPort(short srcPort) {
+    public void setSrcPort(OFPort srcPort) {
         this.srcPort = srcPort;
     }
 
-    public void setDst(long dst) {
+    public void setDst(DatapathId dst) {
         this.dst = dst;
     }
 
-    public void setDstPort(short dstPort) {
+    public void setDstPort(OFPort dstPort) {
         this.dstPort = dstPort;
     }
 
@@ -90,10 +84,10 @@ public class Link implements Comparable<Link> {
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + (int) (dst ^ (dst >>> 32));
-        result = prime * result + dstPort;
-        result = prime * result + (int) (src ^ (src >>> 32));
-        result = prime * result + srcPort;
+        result = prime * result + (int) (dst.getLong() ^ (dst.getLong() >>> 32));
+        result = prime * result + dstPort.getPortNumber();
+        result = prime * result + (int) (src.getLong() ^ (src.getLong() >>> 32));
+        result = prime * result + srcPort.getPortNumber();
         return result;
     }
 
@@ -120,35 +114,36 @@ public class Link implements Comparable<Link> {
 
     @Override
     public String toString() {
-        return "Link [src=" + HexString.toHexString(this.src) 
+        return "Link [src=" + this.src.toString() 
                 + " outPort="
-                + (srcPort & 0xffff)
-                + ", dst=" + HexString.toHexString(this.dst)
+                + srcPort.toString()
+                + ", dst=" + this.dst.toString()
                 + ", inPort="
-                + (dstPort & 0xffff)
+                + dstPort.toString()
                 + "]";
     }
     
+    //TODO @Ryan there was some short 0xFFFF bitmasking here when ports were shorts. I don't get what that did other than just allow all bits of the short (16), so I just stringified the whole thing
     public String toKeyString() {
-    	return (HexString.toHexString(this.src) + "|" +
-    			(this.srcPort & 0xffff) + "|" +
-    			HexString.toHexString(this.dst) + "|" +
-    		    (this.dstPort & 0xffff) );
+    	return (this.src.toString() + "|" +
+    			this.srcPort.toString() + "|" +
+    			this.dst.toString() + "|" +
+    		    this.dstPort.toString());
     }
 
     @Override
     public int compareTo(Link a) {
         // compare link based on natural ordering - src id, src port, dst id, dst port
         if (this.getSrc() != a.getSrc())
-            return (int) (this.getSrc() - a.getSrc());
+            return (int) (this.getSrc().getLong() - a.getSrc().getLong());
         
         if (this.getSrcPort() != a.getSrcPort())
-            return (int) (this.getSrc() - a.getSrc());
+            return (int) (this.getSrc().getLong() - a.getSrc().getLong());
         
         if (this.getDst() != a.getDst())
-            return (int) (this.getDst() - a.getDst());
+            return (int) (this.getDst().getLong() - a.getDst().getLong());
         
-        return this.getDstPort() - a.getDstPort();
+        return this.getDstPort().getPortNumber() - a.getDstPort().getPortNumber();
     }
 }
 
diff --git a/src/main/java/net/floodlightcontroller/routing/Route.java b/src/main/java/net/floodlightcontroller/routing/Route.java
index da00d50b7..f41a9aaf1 100755
--- a/src/main/java/net/floodlightcontroller/routing/Route.java
+++ b/src/main/java/net/floodlightcontroller/routing/Route.java
@@ -20,6 +20,8 @@ package net.floodlightcontroller.routing;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.projectfloodlight.openflow.types.DatapathId;
+
 import net.floodlightcontroller.topology.NodePortTuple;
 
 /**
@@ -39,7 +41,7 @@ public class Route implements Comparable<Route> {
         this.routeCount = 0; // useful if multipath routing available
     }
 
-    public Route(Long src, Long dst) {
+    public Route(DatapathId src, DatapathId dst) {
         super();
         this.id = new RouteId(src, dst);
         this.switchPorts = new ArrayList<NodePortTuple>();
diff --git a/src/main/java/net/floodlightcontroller/routing/RouteId.java b/src/main/java/net/floodlightcontroller/routing/RouteId.java
index 511db7359..bd80f4d2c 100755
--- a/src/main/java/net/floodlightcontroller/routing/RouteId.java
+++ b/src/main/java/net/floodlightcontroller/routing/RouteId.java
@@ -17,7 +17,7 @@
 
 package net.floodlightcontroller.routing;
 
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.types.DatapathId;
 
 /**
  * Stores the endpoints of a route, in this case datapath ids
@@ -25,37 +25,37 @@ import org.openflow.util.HexString;
  * @author David Erickson (daviderickson@cs.stanford.edu)
  */
 public class RouteId implements Cloneable, Comparable<RouteId> {
-    protected Long src;
-    protected Long dst;
+    protected DatapathId src;
+    protected DatapathId dst;
     protected long cookie;
 
-    public RouteId(Long src, Long dst) {
+    public RouteId(DatapathId src, DatapathId dst) {
         super();
         this.src = src;
         this.dst = dst;
         this.cookie = 0;
     }
 
-    public RouteId(Long src, Long dst, long cookie) {
+    public RouteId(DatapathId src, DatapathId dst, long cookie) {
         super();
         this.src = src;
         this.dst = dst;
         this.cookie = cookie;
     }
 
-    public Long getSrc() {
+    public DatapathId getSrc() {
         return src;
     }
 
-    public void setSrc(Long src) {
+    public void setSrc(DatapathId src) {
         this.src = src;
     }
 
-    public Long getDst() {
+    public DatapathId getDst() {
         return dst;
     }
 
-    public void setDst(Long dst) {
+    public void setDst(DatapathId dst) {
         this.dst = dst;
     }
 
@@ -103,8 +103,8 @@ public class RouteId implements Cloneable, Comparable<RouteId> {
 
     @Override
     public String toString() {
-        return "RouteId [src=" + HexString.toHexString(this.src) + " dst="
-                + HexString.toHexString(this.dst) + "]";
+        return "RouteId [src=" + this.src.toString() + " dst="
+                + this.dst.toString() + "]";
     }
 
     @Override
diff --git a/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java b/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java
index aa4b3dde8..2d487f409 100644
--- a/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java
+++ b/src/main/java/net/floodlightcontroller/routing/RoutingDecision.java
@@ -20,6 +20,10 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.devicemanager.IDevice;
 import net.floodlightcontroller.devicemanager.SwitchPort;
@@ -28,15 +32,15 @@ import net.floodlightcontroller.devicemanager.SwitchPort;
 public class RoutingDecision implements IRoutingDecision {
 
     protected RoutingAction action;
-    protected Integer wildcards;
+    protected Match.Builder wildcards;
     protected short hardTimeout;
     protected SwitchPort srcPort;
     protected IDevice srcDevice;
     protected List<IDevice> destDevices;
     protected List<SwitchPort> broadcastIntertfaces;
 
-    public RoutingDecision(long swDipd,
-                                  short inPort,
+    public RoutingDecision(DatapathId swDipd,
+                                  OFPort inPort,
                                   IDevice srcDevice,
                                   RoutingAction action) {
         this.srcPort = new SwitchPort(swDipd, inPort);
@@ -93,12 +97,12 @@ public class RoutingDecision implements IRoutingDecision {
     }
     
     @Override
-    public Integer getWildcards() {
+    public Match.Builder getWildcards() {
         return this.wildcards;
     }
     
     @Override
-    public void setWildcards(Integer wildcards) {
+    public void setWildcards(Match.Builder wildcards) {
         this.wildcards = wildcards;
     }
    
@@ -120,6 +124,6 @@ public class RoutingDecision implements IRoutingDecision {
     public String toString() {
         return "action " + action +
                " wildcard " +
-               ((wildcards == null) ? null : "0x"+Integer.toHexString(wildcards.intValue()));
+               ((wildcards == null) ? null : wildcards.toString());
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/topology/Cluster.java b/src/main/java/net/floodlightcontroller/topology/Cluster.java
index e4ea23b8c..914740f10 100644
--- a/src/main/java/net/floodlightcontroller/topology/Cluster.java
+++ b/src/main/java/net/floodlightcontroller/topology/Cluster.java
@@ -23,37 +23,37 @@ import java.util.Set;
 
 import net.floodlightcontroller.routing.Link;
 
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.types.DatapathId;
 
 public class Cluster {
-    protected long id; // the lowest id of the nodes
-    protected Map<Long, Set<Link>> links; // set of links connected to a node.
+    protected DatapathId id; // the lowest id of the nodes
+    protected Map<DatapathId, Set<Link>> links; // set of links connected to a node.
 
     public Cluster() {
-        id = Long.MAX_VALUE;
-        links = new HashMap<Long, Set<Link>>();
+        id = DatapathId.NONE;
+        links = new HashMap<DatapathId, Set<Link>>();
     }
 
-    public long getId() {
+    public DatapathId getId() {
         return id;
     }
 
-    public void setId(long id) {
+    public void setId(DatapathId id) {
         this.id = id;
     }
 
-    public Map<Long, Set<Link>> getLinks() {
+    public Map<DatapathId, Set<Link>> getLinks() {
         return links;
     }
 
-    public Set<Long> getNodes() {
+    public Set<DatapathId> getNodes() {
         return links.keySet();
     }
 
-    void add(long n) {
+    void add(DatapathId n) {
         if (links.containsKey(n) == false) {
             links.put(n, new HashSet<Link>());
-            if (n < id) id = n;
+            if (n.getLong() < id.getLong()) id = n;
         }
     }
 
@@ -67,7 +67,7 @@ public class Cluster {
 
     @Override 
     public int hashCode() {
-        return (int) (id + id >>>32);
+        return (int) (id.getLong() + id.getLong() >>>32);
     }
 
     @Override
@@ -84,6 +84,6 @@ public class Cluster {
     }
     
     public String toString() {
-        return "[Cluster id=" + HexString.toHexString(id) + ", " + links.keySet() + "]";
+        return "[Cluster id=" + id.toString() + ", " + links.keySet() + "]";
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
index d518b80d2..d6bd17755 100644
--- a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
+++ b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
@@ -19,192 +19,195 @@ package net.floodlightcontroller.topology;
 import java.util.Date;
 import java.util.Set;
 
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+
 import net.floodlightcontroller.core.module.IFloodlightService;
 
 public interface ITopologyService extends IFloodlightService  {
 
-    public void addListener(ITopologyListener listener);
-
-    public Date getLastUpdateTime();
-
-    /**
-     * Query to determine if devices must be learned on a given switch port.
-     */
-    public boolean isAttachmentPointPort(long switchid, short port);
-    public boolean isAttachmentPointPort(long switchid, short port,
-                                         boolean tunnelEnabled);
-
-    public long getOpenflowDomainId(long switchId);
-    public long getOpenflowDomainId(long switchId, boolean tunnelEnabled);
-
-    /**
-     * Returns the identifier of the L2 domain of a given switch.
-     * @param switchId The DPID of the switch in long form
-     * @return The DPID of the switch that is the key for the cluster
-     */
-    public long getL2DomainId(long switchId);
-    public long getL2DomainId(long switchId, boolean tunnelEnabled);
-
-    /**
-     * Queries whether two switches are in the same cluster.
-     * @param switch1
-     * @param switch2
-     * @return true if the switches are in the same cluster
-     */
-    public boolean inSameOpenflowDomain(long switch1, long switch2);
-    public boolean inSameOpenflowDomain(long switch1, long switch2,
-                                        boolean tunnelEnabled);
-
-    public Set<Long> getSwitchesInOpenflowDomain(long switchDPID);
-    public Set<Long> getSwitchesInOpenflowDomain(long switchDPID,
-                                                 boolean tunnelEnabled);
-
-    /**
-     * Queries whether two switches are in the same island.
-     * Currently, island and cluster are the same. In future,
-     * islands could be different than clusters.
-     * @param switch1
-     * @param switch2
-     * @return True of they are in the same island, false otherwise
-     */
-    public boolean inSameL2Domain(long switch1, long switch2);
-    public boolean inSameL2Domain(long switch1, long switch2,
-                                  boolean tunnelEnabled);
-
-    public boolean isBroadcastDomainPort(long sw, short port);
-    public boolean isBroadcastDomainPort(long sw, short port,
-                                         boolean tunnelEnabled);
-
-
-    public boolean isAllowed(long sw, short portId);
-    public boolean isAllowed(long sw, short portId, boolean tunnelEnabled);
-
-    /**
-     * Indicates if an attachment point on the new switch port is consistent
-     * with the attachment point on the old switch port or not.
-     */
-    public boolean isConsistent(long oldSw, short oldPort,
-                                long newSw, short newPort);
-    public boolean isConsistent(long oldSw, short oldPort,
-                                long newSw, short newPort,
-                                boolean tunnelEnabled);
-
-    /**
-     * Indicates if the two switch ports are connected to the same
-     * broadcast domain or not.
-     * @param s1
-     * @param p1
-     * @param s2
-     * @param p2
-     * @return
-     */
-    public boolean isInSameBroadcastDomain(long s1, short p1,
-                                           long s2, short p2);
-    public boolean isInSameBroadcastDomain(long s1, short p1,
-                                           long s2, short p2,
-                                           boolean tunnelEnabled);
-
-    /**
-     * Gets a list of ports on a given switch that are known to topology.
-     * @param sw The switch DPID in long
-     * @return The set of ports on this switch
-     */
-    public Set<Short> getPortsWithLinks(long sw);
-    public Set<Short> getPortsWithLinks(long sw, boolean tunnelEnabled);
-
-    /** Get broadcast ports on a target switch for a given attachmentpoint
-     * point port.
-     */
-    public Set<Short> getBroadcastPorts(long targetSw, long src, short srcPort);
-
-    public Set<Short> getBroadcastPorts(long targetSw, long src, short srcPort,
-                                        boolean tunnelEnabled);
-
-    /**
-     *
-     */
-    public boolean isIncomingBroadcastAllowed(long sw, short portId);
-    public boolean isIncomingBroadcastAllowed(long sw, short portId,
-                                              boolean tunnelEnabled);
-
-
-    /** Get the proper outgoing switchport for a given pair of src-dst
-     * switchports.
-     */
-    public NodePortTuple getOutgoingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort);
-
-
-    public NodePortTuple getOutgoingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort,
-                                               boolean tunnelEnabled);
-
-
-    public NodePortTuple getIncomingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort);
-    public NodePortTuple getIncomingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort,
-                                               boolean tunnelEnabled);
-
-    /**
-     * If the dst is not allowed by the higher-level topology,
-     * this method provides the topologically equivalent broadcast port.
-     * @param src
-     * @param dst
-     * @return the allowed broadcast port
-     */
-    public NodePortTuple
-    getAllowedOutgoingBroadcastPort(long src,
-                                    short srcPort,
-                                    long dst,
-                                    short dstPort);
-
-    public NodePortTuple
-    getAllowedOutgoingBroadcastPort(long src,
-                                    short srcPort,
-                                    long dst,
-                                    short dstPort,
-                                    boolean tunnelEnabled);
-
-    /**
-     * If the src broadcast domain port is not allowed for incoming
-     * broadcast, this method provides the topologically equivalent
-     * incoming broadcast-allowed
-     * src port.
-     * @param src
-     * @param dst
-     * @return the allowed broadcast port
-     */
-    public NodePortTuple
-    getAllowedIncomingBroadcastPort(long src,
-                                    short srcPort);
-
-    public NodePortTuple
-    getAllowedIncomingBroadcastPort(long src,
-                                    short srcPort,
-                                    boolean tunnelEnabled);
-
-
-    /**
-     * Gets the set of ports that belong to a broadcast domain.
-     * @return The set of ports that belong to a broadcast domain.
-     */
-    public Set<NodePortTuple> getBroadcastDomainPorts();
-    public Set<NodePortTuple> getTunnelPorts();
-
-
-    /**
-     * Returns a set of blocked ports.  The set of blocked
-     * ports is the union of all the blocked ports across all
-     * instances.
-     * @return
-     */
-    public Set<NodePortTuple> getBlockedPorts();
-
-    /**
-     * Returns the enabled, non quarantined ports of the given switch. Returns
-     * an empty set if switch doesn't exists, doesn't have any enabled port, or
-     * has only quarantined ports. Will never return null.
-     */
-    public Set<Short> getPorts(long sw);
+	public void addListener(ITopologyListener listener);
+
+	public Date getLastUpdateTime();
+
+	/**
+	 * Query to determine if devices must be learned on a given switch port.
+	 */
+	public boolean isAttachmentPointPort(DatapathId switchid, OFPort port);
+	public boolean isAttachmentPointPort(DatapathId switchid, OFPort port,
+			boolean tunnelEnabled);
+
+	public DatapathId getOpenflowDomainId(DatapathId switchId);
+	public DatapathId getOpenflowDomainId(DatapathId switchId, boolean tunnelEnabled);
+
+	/**
+	 * Returns the identifier of the L2 domain of a given switch.
+	 * @param switchId The DPID of the switch in long form
+	 * @return The DPID of the switch that is the key for the cluster
+	 */
+	public DatapathId getL2DomainId(DatapathId switchId);
+	public DatapathId getL2DomainId(DatapathId switchId, boolean tunnelEnabled);
+
+	/**
+	 * Queries whether two switches are in the same cluster.
+	 * @param switch1
+	 * @param switch2
+	 * @return true if the switches are in the same cluster
+	 */
+	public boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2);
+	public boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2,
+			boolean tunnelEnabled);
+
+	public Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchDPID);
+	public Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchDPID,
+			boolean tunnelEnabled);
+
+	/**
+	 * Queries whether two switches are in the same island.
+	 * Currently, island and cluster are the same. In future,
+	 * islands could be different than clusters.
+	 * @param switch1
+	 * @param switch2
+	 * @return True of they are in the same island, false otherwise
+	 */
+	public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2);
+	public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2,
+			boolean tunnelEnabled);
+
+	public boolean isBroadcastDomainPort(DatapathId sw, OFPort port);
+	public boolean isBroadcastDomainPort(DatapathId sw, OFPort port,
+			boolean tunnelEnabled);
+
+
+	public boolean isAllowed(DatapathId sw, OFPort portId);
+	public boolean isAllowed(DatapathId sw, OFPort portId, boolean tunnelEnabled);
+
+	/**
+	 * Indicates if an attachment point on the new switch port is consistent
+	 * with the attachment point on the old switch port or not.
+	 */
+	public boolean isConsistent(DatapathId oldSw, OFPort oldPort,
+			DatapathId newSw, OFPort newPort);
+	public boolean isConsistent(DatapathId oldSw, OFPort oldPort,
+			DatapathId newSw, OFPort newPort,
+			boolean tunnelEnabled);
+
+	/**
+	 * Indicates if the two switch ports are connected to the same
+	 * broadcast domain or not.
+	 * @param s1
+	 * @param p1
+	 * @param s2
+	 * @param p2
+	 * @return
+	 */
+	public boolean isInSameBroadcastDomain(DatapathId s1, OFPort p1,
+			DatapathId s2, OFPort p2);
+	public boolean isInSameBroadcastDomain(DatapathId s1, OFPort p1,
+			DatapathId s2, OFPort p2,
+			boolean tunnelEnabled);
+
+	/**
+	 * Gets a list of ports on a given switch that are known to topology.
+	 * @param sw The switch DPID in long
+	 * @return The set of ports on this switch
+	 */
+	public Set<OFPort> getPortsWithLinks(DatapathId sw);
+	public Set<OFPort> getPortsWithLinks(DatapathId sw, boolean tunnelEnabled);
+
+	/** Get broadcast ports on a target switch for a given attachmentpoint
+	 * point port.
+	 */
+	public Set<OFPort> getBroadcastPorts(DatapathId targetSw, DatapathId src, OFPort srcPort);
+
+	public Set<OFPort> getBroadcastPorts(DatapathId targetSw, DatapathId src, OFPort srcPort,
+			boolean tunnelEnabled);
+
+	/**
+	 *
+	 */
+	public boolean isIncomingBroadcastAllowed(DatapathId sw, OFPort portId);
+	public boolean isIncomingBroadcastAllowed(DatapathId sw, OFPort portId,
+			boolean tunnelEnabled);
+
+
+	/** Get the proper outgoing switchport for a given pair of src-dst
+	 * switchports.
+	 */
+	public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort,
+			DatapathId dst, OFPort dstPort);
+
+
+	public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort,
+			DatapathId dst, OFPort dstPort,
+			boolean tunnelEnabled);
+
+
+	public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort,
+			DatapathId dst, OFPort dstPort);
+	public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort,
+			DatapathId dst, OFPort dstPort,
+			boolean tunnelEnabled);
+
+	/**
+	 * If the dst is not allowed by the higher-level topology,
+	 * this method provides the topologically equivalent broadcast port.
+	 * @param src
+	 * @param dst
+	 * @return the allowed broadcast port
+	 */
+	public NodePortTuple
+	getAllowedOutgoingBroadcastPort(DatapathId src,
+			OFPort srcPort,
+			DatapathId dst,
+			OFPort dstPort);
+
+	public NodePortTuple
+	getAllowedOutgoingBroadcastPort(DatapathId src,
+			OFPort srcPort,
+			DatapathId dst,
+			OFPort dstPort,
+			boolean tunnelEnabled);
+
+	/**
+	 * If the src broadcast domain port is not allowed for incoming
+	 * broadcast, this method provides the topologically equivalent
+	 * incoming broadcast-allowed
+	 * src port.
+	 * @param src
+	 * @param dst
+	 * @return the allowed broadcast port
+	 */
+	public NodePortTuple
+	getAllowedIncomingBroadcastPort(DatapathId src,
+			OFPort srcPort);
+
+	public NodePortTuple
+	getAllowedIncomingBroadcastPort(DatapathId src,
+			OFPort srcPort,
+			boolean tunnelEnabled);
+
+
+	/**
+	 * Gets the set of ports that belong to a broadcast domain.
+	 * @return The set of ports that belong to a broadcast domain.
+	 */
+	public Set<NodePortTuple> getBroadcastDomainPorts();
+	public Set<NodePortTuple> getTunnelPorts();
+
+
+	/**
+	 * Returns a set of blocked ports.  The set of blocked
+	 * ports is the union of all the blocked ports across all
+	 * instances.
+	 * @return
+	 */
+	public Set<NodePortTuple> getBlockedPorts();
+
+	/**
+	 * Returns the enabled, non quarantined ports of the given switch. Returns
+	 * an empty set if switch doesn't exists, doesn't have any enabled port, or
+	 * has only quarantined ports. Will never return null.
+	 */
+	public Set<OFPort> getPorts(DatapathId sw);
 }
diff --git a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
index 8c5645143..f7b0a178a 100644
--- a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
+++ b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
@@ -21,7 +21,10 @@ import net.floodlightcontroller.core.web.serializers.UShortSerializer;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.openflow.util.HexString;
+
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.util.HexString;
 
 /**
  * A NodePortTuple is similar to a SwitchPortTuple
@@ -31,51 +34,46 @@ import org.openflow.util.HexString;
  */
 
 public class NodePortTuple implements Comparable<NodePortTuple> {
-    protected long nodeId; // switch DPID
-    protected short portId; // switch port id
+    protected DatapathId nodeId; // switch DPID
+    protected OFPort portId; // switch port id
 
     /**
      * Creates a NodePortTuple
      * @param nodeId The DPID of the switch
      * @param portId The port of the switch
      */
-    public NodePortTuple(long nodeId, short portId) {
+    public NodePortTuple(DatapathId nodeId, OFPort portId) {
         this.nodeId = nodeId;
         this.portId = portId;
     }
 
-    public NodePortTuple(long nodeId, int portId) {
-        this.nodeId = nodeId;
-        this.portId = (short) portId;
-    }
-
     @JsonProperty("switch")
     @JsonSerialize(using=DPIDSerializer.class)
-    public long getNodeId() {
+    public DatapathId getNodeId() {
         return nodeId;
     }
-    public void setNodeId(long nodeId) {
+    public void setNodeId(DatapathId nodeId) {
         this.nodeId = nodeId;
     }
     @JsonProperty("port")
     @JsonSerialize(using=UShortSerializer.class)
-    public short getPortId() {
+    public OFPort getPortId() {
         return portId;
     }
-    public void setPortId(short portId) {
+    public void setPortId(OFPort portId) {
         this.portId = portId;
     }
     
     public String toString() {
-        return "[id=" + HexString.toHexString(nodeId) + ", port=" + new Short(portId) + "]";
+        return "[id=" + nodeId.toString() + ", port=" + portId.toString() + "]";
     }
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + (int) (nodeId ^ (nodeId >>> 32));
-        result = prime * result + portId;
+        result = prime * result + (int) (nodeId.getLong() ^ (nodeId.getLong() >>> 32));
+        result = prime * result + portId.getPortNumber();
         return result;
     }
 
@@ -102,7 +100,7 @@ public class NodePortTuple implements Comparable<NodePortTuple> {
      * @return
      */
     public String toKeyString() {
-        return (HexString.toHexString(nodeId)+ "|" + (portId & 0xffff));
+        return (nodeId.toString()+ "|" + portId.toString());
     }
 
     @Override
@@ -111,14 +109,14 @@ public class NodePortTuple implements Comparable<NodePortTuple> {
         final int EQUAL = 0;
         final int AFTER = 1;
 
-        if (this.getNodeId() < obj.getNodeId())
+        if (this.getNodeId().getLong() < obj.getNodeId().getLong())
             return BEFORE;
-        if (this.getNodeId() > obj.getNodeId())
+        if (this.getNodeId().getLong() > obj.getNodeId().getLong())
             return AFTER;
 
-        if (this.getPortId() < obj.getPortId())
+        if (this.getPortId().getPortNumber() < obj.getPortId().getPortNumber())
             return BEFORE;
-        if (this.getPortId() > obj.getPortId())
+        if (this.getPortId().getPortNumber() > obj.getPortId().getPortNumber())
             return AFTER;
 
         return EQUAL;
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
index a143d45e7..bc5d62678 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java
@@ -25,7 +25,8 @@ import java.util.Map;
 import java.util.PriorityQueue;
 import java.util.Set;
 
-
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFPort;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -59,7 +60,7 @@ public class TopologyInstance {
 
     protected static Logger log = LoggerFactory.getLogger(TopologyInstance.class);
 
-    protected Map<Long, Set<Short>> switchPorts; // Set of ports for each switch
+    protected Map<DatapathId, Set<OFPort>> switchPorts; // Set of ports for each switch
     /** Set of switch ports that are marked as blocked.  A set of blocked
      * switch ports may be provided at the time of instantiation. In addition,
      * we may add additional ports to this set.
@@ -69,17 +70,17 @@ public class TopologyInstance {
     /** Set of links that are blocked. */
     protected Set<Link> blockedLinks;
 
-    protected Set<Long> switches;
+    protected Set<DatapathId> switches;
     protected Set<NodePortTuple> broadcastDomainPorts;
     protected Set<NodePortTuple> tunnelPorts;
 
     protected Set<Cluster> clusters;  // set of openflow domains
-    protected Map<Long, Cluster> switchClusterMap; // switch to OF domain map
+    protected Map<DatapathId, Cluster> switchClusterMap; // switch to OF domain map
 
     // States for routing
-    protected Map<Long, BroadcastTree> destinationRootedTrees;
-    protected Map<Long, Set<NodePortTuple>> clusterBroadcastNodePorts;
-    protected Map<Long, BroadcastTree> clusterBroadcastTrees;
+    protected Map<DatapathId, BroadcastTree> destinationRootedTrees;
+    protected Map<DatapathId, Set<NodePortTuple>> clusterBroadcastNodePorts;
+    protected Map<DatapathId, BroadcastTree> clusterBroadcastTrees;
 
     protected class PathCacheLoader extends CacheLoader<RouteId, Route> {
         TopologyInstance ti;
@@ -99,8 +100,8 @@ public class TopologyInstance {
     protected LoadingCache<RouteId, Route> pathcache;
 
     public TopologyInstance() {
-        this.switches = new HashSet<Long>();
-        this.switchPorts = new HashMap<Long, Set<Short>>();
+        this.switches = new HashSet<DatapathId>();
+        this.switchPorts = new HashMap<DatapathId, Set<OFPort>>();
         this.switchPortLinks = new HashMap<NodePortTuple, Set<Link>>();
         this.broadcastDomainPorts = new HashSet<NodePortTuple>();
         this.tunnelPorts = new HashSet<NodePortTuple>();
@@ -108,12 +109,12 @@ public class TopologyInstance {
         this.blockedLinks = new HashSet<Link>();
     }
 
-    public TopologyInstance(Map<Long, Set<Short>> switchPorts,
+    public TopologyInstance(Map<DatapathId, Set<OFPort>> switchPorts,
                             Map<NodePortTuple, Set<Link>> switchPortLinks,
                             Set<NodePortTuple> broadcastDomainPorts)
     {
-        this.switches = new HashSet<Long>(switchPorts.keySet());
-        this.switchPorts = new HashMap<Long, Set<Short>>(switchPorts);
+        this.switches = new HashSet<DatapathId>(switchPorts.keySet());
+        this.switchPorts = new HashMap<DatapathId, Set<OFPort>>(switchPorts);
         this.switchPortLinks = new HashMap<NodePortTuple,
                 Set<Link>>(switchPortLinks);
         this.broadcastDomainPorts = new HashSet<NodePortTuple>(broadcastDomainPorts);
@@ -122,19 +123,19 @@ public class TopologyInstance {
         this.blockedLinks = new HashSet<Link>();
 
         clusters = new HashSet<Cluster>();
-        switchClusterMap = new HashMap<Long, Cluster>();
+        switchClusterMap = new HashMap<DatapathId, Cluster>();
     }
-    public TopologyInstance(Map<Long, Set<Short>> switchPorts,
+    public TopologyInstance(Map<DatapathId, Set<OFPort>> switchPorts,
                             Set<NodePortTuple> blockedPorts,
                             Map<NodePortTuple, Set<Link>> switchPortLinks,
                             Set<NodePortTuple> broadcastDomainPorts,
                             Set<NodePortTuple> tunnelPorts){
 
         // copy these structures
-        this.switches = new HashSet<Long>(switchPorts.keySet());
-        this.switchPorts = new HashMap<Long, Set<Short>>();
-        for(long sw: switchPorts.keySet()) {
-            this.switchPorts.put(sw, new HashSet<Short>(switchPorts.get(sw)));
+        this.switches = new HashSet<DatapathId>(switchPorts.keySet());
+        this.switchPorts = new HashMap<DatapathId, Set<OFPort>>();
+        for(DatapathId sw: switchPorts.keySet()) {
+            this.switchPorts.put(sw, new HashSet<OFPort>(switchPorts.get(sw)));
         }
 
         this.blockedPorts = new HashSet<NodePortTuple>(blockedPorts);
@@ -148,10 +149,10 @@ public class TopologyInstance {
 
         blockedLinks = new HashSet<Link>();
         clusters = new HashSet<Cluster>();
-        switchClusterMap = new HashMap<Long, Cluster>();
-        destinationRootedTrees = new HashMap<Long, BroadcastTree>();
-        clusterBroadcastTrees = new HashMap<Long, BroadcastTree>();
-        clusterBroadcastNodePorts = new HashMap<Long, Set<NodePortTuple>>();
+        switchClusterMap = new HashMap<DatapathId, Cluster>();
+        destinationRootedTrees = new HashMap<DatapathId, BroadcastTree>();
+        clusterBroadcastTrees = new HashMap<DatapathId, BroadcastTree>();
+        clusterBroadcastNodePorts = new HashMap<DatapathId, Set<NodePortTuple>>();
 
         pathcache = CacheBuilder.newBuilder().concurrencyLevel(4)
                     .maximumSize(1000L)
@@ -204,9 +205,9 @@ public class TopologyInstance {
     }
 
     protected void addLinksToOpenflowDomains() {
-        for(long s: switches) {
+        for(DatapathId s: switches) {
             if (switchPorts.get(s) == null) continue;
-            for (short p: switchPorts.get(s)) {
+            for (OFPort p: switchPorts.get(s)) {
                 NodePortTuple np = new NodePortTuple(s, p);
                 if (switchPortLinks.get(np) == null) continue;
                 if (isBroadcastDomainPort(np)) continue;
@@ -242,17 +243,17 @@ public class TopologyInstance {
             explanation="The internal state of the topology module is corrupt",
             recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
     public void identifyOpenflowDomains() {
-        Map<Long, ClusterDFS> dfsList = new HashMap<Long, ClusterDFS>();
+        Map<DatapathId, ClusterDFS> dfsList = new HashMap<DatapathId, ClusterDFS>();
 
         if (switches == null) return;
 
-        for (Long key: switches) {
+        for (DatapathId key: switches) {
             ClusterDFS cdfs = new ClusterDFS();
             dfsList.put(key, cdfs);
         }
-        Set<Long> currSet = new HashSet<Long>();
+        Set<DatapathId> currSet = new HashSet<DatapathId>();
 
-        for (Long sw: switches) {
+        for (DatapathId sw: switches) {
             ClusterDFS cdfs = dfsList.get(sw);
             if (cdfs == null) {
                 log.error("No DFS object for switch {} found.", sw);
@@ -291,15 +292,15 @@ public class TopologyInstance {
      * @param currSet: Set of nodes in the current cluster in formation
      * @return long: DSF index to be used when a new node is visited
      */
-    private long dfsTraverse (long parentIndex, long currIndex, long currSw,
-                              Map<Long, ClusterDFS> dfsList, Set <Long> currSet) {
+    private long dfsTraverse (long parentIndex, long currIndex, DatapathId currSw,
+                              Map<DatapathId, ClusterDFS> dfsList, Set <DatapathId> currSet) {
 
         //Get the DFS object corresponding to the current switch
         ClusterDFS currDFS = dfsList.get(currSw);
         // Get all the links corresponding to this switch
 
-        Set<Long> nodesInMyCluster = new HashSet<Long>();
-        Set<Long> myCurrSet = new HashSet<Long>();
+        Set<DatapathId> nodesInMyCluster = new HashSet<DatapathId>();
+        Set<DatapathId> myCurrSet = new HashSet<DatapathId>();
 
         //Assign the DFS object with right values.
         currDFS.setVisited(true);
@@ -309,14 +310,14 @@ public class TopologyInstance {
 
         // Traverse the graph through every outgoing link.
         if (switchPorts.get(currSw) != null){
-            for(Short p: switchPorts.get(currSw)) {
+            for(OFPort p: switchPorts.get(currSw)) {
                 Set<Link> lset = switchPortLinks.get(new NodePortTuple(currSw, p));
                 if (lset == null) continue;
                 for(Link l:lset) {
-                    long dstSw = l.getDst();
+                	DatapathId dstSw = l.getDst();
 
                     // ignore incoming links.
-                    if (dstSw == currSw) continue;
+                    if (dstSw.equals(currSw)) continue;
 
                     // ignore if the destination is already added to
                     // another cluster
@@ -368,7 +369,7 @@ public class TopologyInstance {
             // create a new switch cluster and the switches in the current
             // set to the switch cluster.
             Cluster sc = new Cluster();
-            for(long sw: currSet){
+            for(DatapathId sw: currSet){
                 sc.add(sw);
                 switchClusterMap.put(sw, sc);
             }
@@ -425,8 +426,8 @@ public class TopologyInstance {
     }
 
     protected class NodeDist implements Comparable<NodeDist> {
-        private final Long node;
-        public Long getNode() {
+        private final DatapathId node;
+        public DatapathId getNode() {
             return node;
         }
 
@@ -435,7 +436,7 @@ public class TopologyInstance {
             return dist;
         }
 
-        public NodeDist(Long node, int dist) {
+        public NodeDist(DatapathId node, int dist) {
             this.node = node;
             this.dist = dist;
         }
@@ -443,7 +444,7 @@ public class TopologyInstance {
         @Override
         public int compareTo(NodeDist o) {
             if (o.dist == this.dist) {
-                return (int)(this.node - o.node);
+                return (int)(this.node.getLong() - o.node.getLong());
             }
             return this.dist - o.dist;
         }
@@ -478,34 +479,34 @@ public class TopologyInstance {
         }
     }
 
-    protected BroadcastTree dijkstra(Cluster c, Long root,
+    protected BroadcastTree dijkstra(Cluster c, DatapathId root,
                                      Map<Link, Integer> linkCost,
                                      boolean isDstRooted) {
-        HashMap<Long, Link> nexthoplinks = new HashMap<Long, Link>();
+        HashMap<DatapathId, Link> nexthoplinks = new HashMap<DatapathId, Link>();
         //HashMap<Long, Long> nexthopnodes = new HashMap<Long, Long>();
-        HashMap<Long, Integer> cost = new HashMap<Long, Integer>();
+        HashMap<DatapathId, Integer> cost = new HashMap<DatapathId, Integer>();
         int w;
 
-        for (Long node: c.links.keySet()) {
+        for (DatapathId node: c.links.keySet()) {
             nexthoplinks.put(node, null);
             //nexthopnodes.put(node, null);
             cost.put(node, MAX_PATH_WEIGHT);
         }
 
-        HashMap<Long, Boolean> seen = new HashMap<Long, Boolean>();
+        HashMap<DatapathId, Boolean> seen = new HashMap<DatapathId, Boolean>();
         PriorityQueue<NodeDist> nodeq = new PriorityQueue<NodeDist>();
         nodeq.add(new NodeDist(root, 0));
         cost.put(root, 0);
         while (nodeq.peek() != null) {
             NodeDist n = nodeq.poll();
-            Long cnode = n.getNode();
+            DatapathId cnode = n.getNode();
             int cdist = n.getDist();
             if (cdist >= MAX_PATH_WEIGHT) break;
             if (seen.containsKey(cnode)) continue;
             seen.put(cnode, true);
 
             for (Link link: c.links.get(cnode)) {
-                Long neighbor;
+            	DatapathId neighbor;
 
                 if (isDstRooted == true) neighbor = link.getSrc();
                 else neighbor = link.getDst();
@@ -554,7 +555,7 @@ public class TopologyInstance {
         }
 
         for(Cluster c: clusters) {
-            for (Long node : c.links.keySet()) {
+            for (DatapathId node : c.links.keySet()) {
                 BroadcastTree tree = dijkstra(c, node, linkCost, true);
                 destinationRootedTrees.put(node, tree);
             }
@@ -581,9 +582,9 @@ public class TopologyInstance {
             //log.info("Broadcast Tree {}", tree);
 
             Set<NodePortTuple> nptSet = new HashSet<NodePortTuple>();
-            Map<Long, Link> links = tree.getLinks();
+            Map<DatapathId, Link> links = tree.getLinks();
             if (links == null) continue;
-            for(long nodeId: links.keySet()) {
+            for(DatapathId nodeId: links.keySet()) {
                 Link l = links.get(nodeId);
                 if (l == null) continue;
                 NodePortTuple npt1 = new NodePortTuple(l.getSrc(), l.getSrcPort());
@@ -597,8 +598,8 @@ public class TopologyInstance {
 
     protected Route buildroute(RouteId id) {
         NodePortTuple npt;
-        long srcId = id.getSrc();
-        long dstId = id.getDst();
+        DatapathId srcId = id.getSrc();
+        DatapathId dstId = id.getDst();
 
         LinkedList<NodePortTuple> switchPorts =
                 new LinkedList<NodePortTuple>();
@@ -606,7 +607,7 @@ public class TopologyInstance {
         if (destinationRootedTrees == null) return null;
         if (destinationRootedTrees.get(dstId) == null) return null;
 
-        Map<Long, Link> nexthoplinks =
+        Map<DatapathId, Link> nexthoplinks =
                 destinationRootedTrees.get(dstId).getLinks();
 
         if (!switches.contains(srcId) || !switches.contains(dstId)) {
@@ -640,7 +641,7 @@ public class TopologyInstance {
         return result;
     }
 
-    protected int getCost(long srcId, long dstId) {
+    protected int getCost(DatapathId srcId, DatapathId dstId) {
         BroadcastTree bt = destinationRootedTrees.get(dstId);
         if (bt == null) return -1;
         return (bt.getCost(srcId));
@@ -655,7 +656,7 @@ public class TopologyInstance {
     }
 
     // IRoutingEngineService interfaces
-    protected boolean routeExists(long srcId, long dstId) {
+    protected boolean routeExists(DatapathId srcId, DatapathId dstId) {
         BroadcastTree bt = destinationRootedTrees.get(dstId);
         if (bt == null) return false;
         Link link = bt.getLinks().get(srcId);
@@ -663,19 +664,19 @@ public class TopologyInstance {
         return true;
     }
 
-    protected Route getRoute(ServiceChain sc, long srcId, short srcPort,
-                             long dstId, short dstPort, long cookie) {
+    protected Route getRoute(ServiceChain sc, DatapathId srcId, OFPort srcPort,
+    		DatapathId dstId, OFPort dstPort, long cookie) {
 
 
         // Return null the route source and desitnation are the
         // same switchports.
-        if (srcId == dstId && srcPort == dstPort)
+        if (srcId.equals(dstId) && srcPort.equals(dstPort))
             return null;
 
         List<NodePortTuple> nptList;
         NodePortTuple npt;
         Route r = getRoute(srcId, dstId, 0);
-        if (r == null && srcId != dstId) return null;
+        if (r == null && !srcId.equals(dstId)) return null;
 
         if (r != null) {
             nptList= new ArrayList<NodePortTuple>(r.getPath());
@@ -695,9 +696,9 @@ public class TopologyInstance {
     // NOTE: Return a null route if srcId equals dstId.  The null route
     // need not be stored in the cache.  Moreover, the LoadingCache will
     // throw an exception if null route is returned.
-    protected Route getRoute(long srcId, long dstId, long cookie) {
+    protected Route getRoute(DatapathId srcId, DatapathId dstId, long cookie) {
         // Return null route if srcId equals dstId
-        if (srcId == dstId) return null;
+        if (srcId.equals(dstId)) return null;
 
 
         RouteId id = new RouteId(srcId, dstId);
@@ -725,54 +726,54 @@ public class TopologyInstance {
     //  ITopologyService interface method helpers.
     //
 
-    protected boolean isInternalToOpenflowDomain(long switchid, short port) {
+    protected boolean isInternalToOpenflowDomain(DatapathId switchid, OFPort port) {
         return !isAttachmentPointPort(switchid, port);
     }
 
-    public boolean isAttachmentPointPort(long switchid, short port) {
+    public boolean isAttachmentPointPort(DatapathId switchid, OFPort port) {
         NodePortTuple npt = new NodePortTuple(switchid, port);
         if (switchPortLinks.containsKey(npt)) return false;
         return true;
     }
 
-    protected long getOpenflowDomainId(long switchId) {
+    protected DatapathId getOpenflowDomainId(DatapathId switchId) {
         Cluster c = switchClusterMap.get(switchId);
         if (c == null) return switchId;
         return c.getId();
     }
 
-    protected long getL2DomainId(long switchId) {
+    protected DatapathId getL2DomainId(DatapathId switchId) {
         return getOpenflowDomainId(switchId);
     }
 
-    protected Set<Long> getSwitchesInOpenflowDomain(long switchId) {
+    protected Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchId) {
         Cluster c = switchClusterMap.get(switchId);
         if (c == null) {
             // The switch is not known to topology as there
             // are no links connected to it.
-            Set<Long> nodes = new HashSet<Long>();
+            Set<DatapathId> nodes = new HashSet<DatapathId>();
             nodes.add(switchId);
             return nodes;
         }
         return (c.getNodes());
     }
 
-    protected boolean inSameOpenflowDomain(long switch1, long switch2) {
+    protected boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2) {
         Cluster c1 = switchClusterMap.get(switch1);
         Cluster c2 = switchClusterMap.get(switch2);
         if (c1 != null && c2 != null)
-            return (c1.getId() == c2.getId());
-        return (switch1 == switch2);
+            return (c1.getId().equals(c2.getId()));
+        return (switch1.equals(switch2));
     }
 
-    public boolean isAllowed(long sw, short portId) {
+    public boolean isAllowed(DatapathId sw, OFPort portId) {
         return true;
     }
 
     protected boolean
-    isIncomingBroadcastAllowedOnSwitchPort(long sw, short portId) {
+    isIncomingBroadcastAllowedOnSwitchPort(DatapathId sw, OFPort portId) {
         if (isInternalToOpenflowDomain(sw, portId)) {
-            long clusterId = getOpenflowDomainId(sw);
+        	DatapathId clusterId = getOpenflowDomainId(sw);
             NodePortTuple npt = new NodePortTuple(sw, portId);
             if (clusterBroadcastNodePorts.get(clusterId).contains(npt))
                 return true;
@@ -781,52 +782,52 @@ public class TopologyInstance {
         return true;
     }
 
-    public boolean isConsistent(long oldSw, short oldPort, long newSw,
-                                short newPort) {
+    public boolean isConsistent(DatapathId oldSw, OFPort oldPort, DatapathId newSw,
+                                OFPort newPort) {
         if (isInternalToOpenflowDomain(newSw, newPort)) return true;
-        return (oldSw == newSw && oldPort == newPort);
+        return (oldSw.equals(newSw) && oldPort.equals(newPort));
     }
 
     protected Set<NodePortTuple>
-    getBroadcastNodePortsInCluster(long sw) {
-        long clusterId = getOpenflowDomainId(sw);
+    getBroadcastNodePortsInCluster(DatapathId sw) {
+    	DatapathId clusterId = getOpenflowDomainId(sw);
         return clusterBroadcastNodePorts.get(clusterId);
     }
 
-    public boolean inSameBroadcastDomain(long s1, short p1, long s2, short p2) {
+    public boolean inSameBroadcastDomain(DatapathId s1, OFPort p1, DatapathId s2, OFPort p2) {
         return false;
     }
 
-    public boolean inSameL2Domain(long switch1, long switch2) {
+    public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2) {
         return inSameOpenflowDomain(switch1, switch2);
     }
 
-    public NodePortTuple getOutgoingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort) {
+    public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort,
+    		DatapathId dst, OFPort dstPort) {
         // Use this function to redirect traffic if needed.
         return new NodePortTuple(dst, dstPort);
     }
 
-    public NodePortTuple getIncomingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort) {
+    public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort,
+    		DatapathId dst, OFPort dstPort) {
         // Use this function to reinject traffic from a
         // different port if needed.
         return new NodePortTuple(src, srcPort);
     }
 
-    public Set<Long> getSwitches() {
+    public Set<DatapathId> getSwitches() {
         return switches;
     }
 
-    public Set<Short> getPortsWithLinks(long sw) {
+    public Set<OFPort> getPortsWithLinks(DatapathId sw) {
         return switchPorts.get(sw);
     }
 
-    public Set<Short> getBroadcastPorts(long targetSw, long src, short srcPort) {
-        Set<Short> result = new HashSet<Short>();
-        long clusterId = getOpenflowDomainId(targetSw);
+    public Set<OFPort> getBroadcastPorts(DatapathId targetSw, DatapathId src, OFPort srcPort) {
+        Set<OFPort> result = new HashSet<OFPort>();
+        DatapathId clusterId = getOpenflowDomainId(targetSw);
         for(NodePortTuple npt: clusterBroadcastNodePorts.get(clusterId)) {
-            if (npt.getNodeId() == targetSw) {
+            if (npt.getNodeId().equals(targetSw)) {
                 result.add(npt.getPortId());
             }
         }
@@ -834,15 +835,13 @@ public class TopologyInstance {
     }
 
     public NodePortTuple
-    getAllowedOutgoingBroadcastPort(long src, short srcPort, long dst,
-                                    short dstPort) {
-        // TODO Auto-generated method stub
+    getAllowedOutgoingBroadcastPort(DatapathId src, OFPort srcPort, DatapathId dst,
+                                    OFPort dstPort) {
         return null;
     }
 
     public NodePortTuple
-    getAllowedIncomingBroadcastPort(long src, short srcPort) {
-        // TODO Auto-generated method stub
+    getAllowedIncomingBroadcastPort(DatapathId src, OFPort srcPort) {
         return null;
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
index 25b91464a..dce7d28b9 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
@@ -33,13 +33,15 @@ import java.util.concurrent.TimeUnit;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.HAListenerTypeMarker;
+import net.floodlightcontroller.core.HARole;
 import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.core.IHAListener;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.LogicalOFMessageCategory;
 import net.floodlightcontroller.core.annotations.LogMessageCategory;
 import net.floodlightcontroller.core.annotations.LogMessageDoc;
+import net.floodlightcontroller.core.internal.IOFSwitchService;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
@@ -50,7 +52,7 @@ import net.floodlightcontroller.debugcounter.IDebugCounter;
 import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterException;
 import net.floodlightcontroller.debugcounter.IDebugCounterService.CounterType;
-import net.floodlightcontroller.debugcounter.NullDebugCounter;
+import net.floodlightcontroller.debugcounter.MockDebugCounterService;
 import net.floodlightcontroller.debugevent.IDebugEventService;
 import net.floodlightcontroller.debugevent.IEventUpdater;
 import net.floodlightcontroller.debugevent.NullDebugEvent;
@@ -70,13 +72,16 @@ import net.floodlightcontroller.routing.Route;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 import net.floodlightcontroller.topology.web.TopologyWebRoutable;
 
-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.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.OFBufferId;
+import org.projectfloodlight.openflow.types.OFPort;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -101,12 +106,12 @@ public class TopologyManager implements
     /**
      * Role of the controller.
      */
-    private Role role;
+    private HARole role;
 
     /**
      * Set of ports for each switch
      */
-    protected Map<Long, Set<Short>> switchPorts;
+    protected Map<DatapathId, Set<OFPort>> switchPorts;
 
     /**
      * Set of links organized by node port tuple
@@ -131,6 +136,7 @@ public class TopologyManager implements
     protected ILinkDiscoveryService linkDiscovery;
     protected IThreadPoolService threadPool;
     protected IFloodlightProviderService floodlightProvider;
+    protected IOFSwitchService switchService;
     protected IRestApiService restApi;
     protected IDebugCounterService debugCounters;
 
@@ -188,11 +194,11 @@ public class TopologyManager implements
     protected class TopologyEventInfo {
         private final int numOpenflowClustersWithTunnels;
         private final int numOpenflowClustersWithoutTunnels;
-        private final Map<Long, List<NodePortTuple>> externalPortsMap;
+        private final Map<DatapathId, List<NodePortTuple>> externalPortsMap;
         private final int numTunnelPorts;
         public TopologyEventInfo(int numOpenflowClustersWithTunnels,
                                  int numOpenflowClustersWithoutTunnels,
-                                 Map<Long, List<NodePortTuple>> externalPortsMap,
+                                 Map<DatapathId, List<NodePortTuple>> externalPortsMap,
                                  int numTunnelPorts) {
             super();
             this.numOpenflowClustersWithTunnels = numOpenflowClustersWithTunnels;
@@ -215,7 +221,7 @@ public class TopologyManager implements
             if (numExternalClusters > 0) {
                 builder.append(" { ");
                 int count = 0;
-                for (Long extCluster : externalPortsMap.keySet()) {
+                for (DatapathId extCluster : externalPortsMap.keySet()) {
                     builder.append("#" + extCluster + ":Ext Ports: ");
                     builder.append(externalPortsMap.get(extCluster).size());
                     if (++count < numExternalClusters) {
@@ -287,7 +293,7 @@ public class TopologyManager implements
             catch (Exception e) {
                 log.error("Error in topology instance task thread", e);
             } finally {
-                if (floodlightProvider.getRole() != Role.SLAVE)
+                if (floodlightProvider.getRole() != HARole.STANDBY)
                     newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS,
                                            TimeUnit.MILLISECONDS);
             }
@@ -348,12 +354,12 @@ public class TopologyManager implements
     }
 
     @Override
-    public boolean isAttachmentPointPort(long switchid, short port) {
+    public boolean isAttachmentPointPort(DatapathId switchid, OFPort port) {
         return isAttachmentPointPort(switchid, port, true);
     }
 
     @Override
-    public boolean isAttachmentPointPort(long switchid, short port,
+    public boolean isAttachmentPointPort(DatapathId switchid, OFPort port,
                                          boolean tunnelEnabled) {
 
         // If the switch port is 'tun-bsn' port, it is not
@@ -371,55 +377,56 @@ public class TopologyManager implements
 
         // Check whether the port is a physical port. We should not learn
         // attachment points on "special" ports.
-        if ((port & 0xff00) == 0xff00 && port != (short)0xfffe) return false;
+        //TODO @Ryan port numbers should be handled as ints now, not shorts. I suppose anything above 65280 up to 65533 is a "special" non-physical port.
+        if ((port.getShortPortNumber() & 0xff00) == 0xff00 && port.getShortPortNumber() != (short)0xfffe) return false;
 
         // Make sure that the port is enabled.
-        IOFSwitch sw = floodlightProvider.getSwitch(switchid);
+        IOFSwitch sw = switchService.getActiveSwitch(switchid);
         if (sw == null) return false;
         return (sw.portEnabled(port));
     }
 
     @Override
-    public long getOpenflowDomainId(long switchId) {
+    public DatapathId getOpenflowDomainId(DatapathId switchId) {
         return getOpenflowDomainId(switchId, true);
     }
 
     @Override
-    public long getOpenflowDomainId(long switchId, boolean tunnelEnabled) {
+    public DatapathId getOpenflowDomainId(DatapathId switchId, boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getOpenflowDomainId(switchId);
     }
 
     @Override
-    public long getL2DomainId(long switchId) {
+    public DatapathId getL2DomainId(DatapathId switchId) {
         return getL2DomainId(switchId, true);
     }
 
     @Override
-    public long getL2DomainId(long switchId, boolean tunnelEnabled) {
+    public DatapathId getL2DomainId(DatapathId switchId, boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getL2DomainId(switchId);
     }
 
     @Override
-    public boolean inSameOpenflowDomain(long switch1, long switch2) {
+    public boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2) {
         return inSameOpenflowDomain(switch1, switch2, true);
     }
 
     @Override
-    public boolean inSameOpenflowDomain(long switch1, long switch2,
+    public boolean inSameOpenflowDomain(DatapathId switch1, DatapathId switch2,
                                         boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.inSameOpenflowDomain(switch1, switch2);
     }
 
     @Override
-    public boolean isAllowed(long sw, short portId) {
+    public boolean isAllowed(DatapathId sw, OFPort portId) {
         return isAllowed(sw, portId, true);
     }
 
     @Override
-    public boolean isAllowed(long sw, short portId, boolean tunnelEnabled) {
+    public boolean isAllowed(DatapathId sw, OFPort portId, boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.isAllowed(sw, portId);
     }
@@ -427,12 +434,12 @@ public class TopologyManager implements
     ////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////
     @Override
-    public boolean isIncomingBroadcastAllowed(long sw, short portId) {
+    public boolean isIncomingBroadcastAllowed(DatapathId sw, OFPort portId) {
         return isIncomingBroadcastAllowed(sw, portId, true);
     }
 
     @Override
-    public boolean isIncomingBroadcastAllowed(long sw, short portId,
+    public boolean isIncomingBroadcastAllowed(DatapathId sw, OFPort portId,
                                               boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.isIncomingBroadcastAllowedOnSwitchPort(sw, portId);
@@ -442,13 +449,13 @@ public class TopologyManager implements
     ////////////////////////////////////////////////////////////////////////
     /** Get all the ports connected to the switch */
     @Override
-    public Set<Short> getPortsWithLinks(long sw) {
+    public Set<OFPort> getPortsWithLinks(DatapathId sw) {
         return getPortsWithLinks(sw, true);
     }
 
     /** Get all the ports connected to the switch */
     @Override
-    public Set<Short> getPortsWithLinks(long sw, boolean tunnelEnabled) {
+    public Set<OFPort> getPortsWithLinks(DatapathId sw, boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getPortsWithLinks(sw);
     }
@@ -460,8 +467,8 @@ public class TopologyManager implements
      * is on switch port (src, srcPort).
      */
     @Override
-    public Set<Short> getBroadcastPorts(long targetSw,
-                                        long src, short srcPort) {
+    public Set<OFPort> getBroadcastPorts(DatapathId targetSw,
+    		DatapathId src, OFPort srcPort) {
         return getBroadcastPorts(targetSw, src, srcPort, true);
     }
 
@@ -470,8 +477,8 @@ public class TopologyManager implements
      * is on switch port (src, srcPort).
      */
     @Override
-    public Set<Short> getBroadcastPorts(long targetSw,
-                                        long src, short srcPort,
+    public Set<OFPort> getBroadcastPorts(DatapathId targetSw,
+    		DatapathId src, OFPort srcPort,
                                         boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getBroadcastPorts(targetSw, src, srcPort);
@@ -480,15 +487,15 @@ public class TopologyManager implements
     ////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////
     @Override
-    public NodePortTuple getOutgoingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort) {
+    public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort,
+    		DatapathId dst, OFPort dstPort) {
         // Use this function to redirect traffic if needed.
         return getOutgoingSwitchPort(src, srcPort, dst, dstPort, true);
     }
 
     @Override
-    public NodePortTuple getOutgoingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort,
+    public NodePortTuple getOutgoingSwitchPort(DatapathId src, OFPort srcPort,
+    		DatapathId dst, OFPort dstPort,
                                                boolean tunnelEnabled) {
         // Use this function to redirect traffic if needed.
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
@@ -499,14 +506,14 @@ public class TopologyManager implements
     ////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////
     @Override
-    public NodePortTuple getIncomingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort) {
+    public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort,
+    		DatapathId dst, OFPort dstPort) {
         return getIncomingSwitchPort(src, srcPort, dst, dstPort, true);
     }
 
     @Override
-    public NodePortTuple getIncomingSwitchPort(long src, short srcPort,
-                                               long dst, short dstPort,
+    public NodePortTuple getIncomingSwitchPort(DatapathId src, OFPort srcPort,
+    		DatapathId dst, OFPort dstPort,
                                                boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getIncomingSwitchPort(src, srcPort,
@@ -519,15 +526,15 @@ public class TopologyManager implements
      * Checks if the two switchports belong to the same broadcast domain.
      */
     @Override
-    public boolean isInSameBroadcastDomain(long s1, short p1, long s2,
-                                           short p2) {
+    public boolean isInSameBroadcastDomain(DatapathId s1, OFPort p1, DatapathId s2,
+    		OFPort p2) {
         return isInSameBroadcastDomain(s1, p1, s2, p2, true);
 
     }
 
     @Override
-    public boolean isInSameBroadcastDomain(long s1, short p1,
-                                           long s2, short p2,
+    public boolean isInSameBroadcastDomain(DatapathId s1, OFPort p1,
+    		DatapathId s2, OFPort p2,
                                            boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.inSameBroadcastDomain(s1, p1, s2, p2);
@@ -540,12 +547,12 @@ public class TopologyManager implements
      * Checks if the switchport is a broadcast domain port or not.
      */
     @Override
-    public boolean isBroadcastDomainPort(long sw, short port) {
+    public boolean isBroadcastDomainPort(DatapathId sw, OFPort port) {
         return isBroadcastDomainPort(sw, port, true);
     }
 
     @Override
-    public boolean isBroadcastDomainPort(long sw, short port,
+    public boolean isBroadcastDomainPort(DatapathId sw, OFPort port,
                                          boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.isBroadcastDomainPort(new NodePortTuple(sw, port));
@@ -558,15 +565,15 @@ public class TopologyManager implements
      * old attachment point port.
      */
     @Override
-    public boolean isConsistent(long oldSw, short oldPort,
-                                long newSw, short newPort) {
+    public boolean isConsistent(DatapathId oldSw, OFPort oldPort,
+    		DatapathId newSw, OFPort newPort) {
         return isConsistent(oldSw, oldPort,
                                             newSw, newPort, true);
     }
 
     @Override
-    public boolean isConsistent(long oldSw, short oldPort,
-                                long newSw, short newPort,
+    public boolean isConsistent(DatapathId oldSw, OFPort oldPort,
+    		DatapathId newSw, OFPort newPort,
                                 boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.isConsistent(oldSw, oldPort, newSw, newPort);
@@ -578,12 +585,12 @@ public class TopologyManager implements
      * Checks if the two switches are in the same Layer 2 domain.
      */
     @Override
-    public boolean inSameL2Domain(long switch1, long switch2) {
+    public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2) {
         return inSameL2Domain(switch1, switch2, true);
     }
 
     @Override
-    public boolean inSameL2Domain(long switch1, long switch2,
+    public boolean inSameL2Domain(DatapathId switch1, DatapathId switch2,
                                   boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.inSameL2Domain(switch1, switch2);
@@ -592,19 +599,19 @@ public class TopologyManager implements
     ////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////
     @Override
-    public NodePortTuple getAllowedOutgoingBroadcastPort(long src,
-                                                         short srcPort,
-                                                         long dst,
-                                                         short dstPort) {
+    public NodePortTuple getAllowedOutgoingBroadcastPort(DatapathId src,
+    		OFPort srcPort,
+                                                         DatapathId dst,
+                                                         OFPort dstPort) {
         return getAllowedOutgoingBroadcastPort(src, srcPort,
                                                dst, dstPort, true);
     }
 
     @Override
-    public NodePortTuple getAllowedOutgoingBroadcastPort(long src,
-                                                         short srcPort,
-                                                         long dst,
-                                                         short dstPort,
+    public NodePortTuple getAllowedOutgoingBroadcastPort(DatapathId src,
+    		OFPort srcPort,
+                                                         DatapathId dst,
+                                                         OFPort dstPort,
                                                          boolean tunnelEnabled){
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getAllowedOutgoingBroadcastPort(src, srcPort,
@@ -614,13 +621,13 @@ public class TopologyManager implements
     ////////////////////////////////////////////////////////////////////////
     @Override
     public NodePortTuple
-    getAllowedIncomingBroadcastPort(long src, short srcPort) {
+    getAllowedIncomingBroadcastPort(DatapathId src, OFPort srcPort) {
         return getAllowedIncomingBroadcastPort(src,srcPort, true);
     }
 
     @Override
     public NodePortTuple
-    getAllowedIncomingBroadcastPort(long src, short srcPort,
+    getAllowedIncomingBroadcastPort(DatapathId src, OFPort srcPort,
                                     boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getAllowedIncomingBroadcastPort(src,srcPort);
@@ -629,12 +636,12 @@ public class TopologyManager implements
     ////////////////////////////////////////////////////////////////////////
     ////////////////////////////////////////////////////////////////////////
     @Override
-    public Set<Long> getSwitchesInOpenflowDomain(long switchDPID) {
+    public Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchDPID) {
         return getSwitchesInOpenflowDomain(switchDPID, true);
     }
 
     @Override
-    public Set<Long> getSwitchesInOpenflowDomain(long switchDPID,
+    public Set<DatapathId> getSwitchesInOpenflowDomain(DatapathId switchDPID,
                                                  boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getSwitchesInOpenflowDomain(switchDPID);
@@ -678,41 +685,41 @@ public class TopologyManager implements
     // ***************
 
     @Override
-    public Route getRoute(long src, long dst, long cookie) {
+    public Route getRoute(DatapathId src, DatapathId dst, long cookie) {
         return getRoute(src, dst, cookie, true);
     }
 
     @Override
-    public Route getRoute(long src, long dst, long cookie, boolean tunnelEnabled) {
+    public Route getRoute(DatapathId src, DatapathId dst, long cookie, boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getRoute(src, dst, cookie);
     }
 
     @Override
-    public Route getRoute(long src, short srcPort, long dst, short dstPort, long cookie) {
+    public Route getRoute(DatapathId src, OFPort srcPort, DatapathId dst, OFPort dstPort, long cookie) {
         return getRoute(src, srcPort, dst, dstPort, cookie, true);
     }
 
     @Override
-    public Route getRoute(long src, short srcPort, long dst, short dstPort, long cookie,
+    public Route getRoute(DatapathId src, OFPort srcPort, DatapathId dst, OFPort dstPort, long cookie,
                           boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.getRoute(null, src, srcPort, dst, dstPort, cookie);
     }
 
     @Override
-    public boolean routeExists(long src, long dst) {
+    public boolean routeExists(DatapathId src, DatapathId dst) {
         return routeExists(src, dst, true);
     }
 
     @Override
-    public boolean routeExists(long src, long dst, boolean tunnelEnabled) {
+    public boolean routeExists(DatapathId src, DatapathId dst, boolean tunnelEnabled) {
         TopologyInstance ti = getCurrentInstance(tunnelEnabled);
         return ti.routeExists(src, dst);
     }
 
     @Override
-    public ArrayList<Route> getRoutes(long srcDpid, long dstDpid,
+    public ArrayList<Route> getRoutes(DatapathId srcDpid, DatapathId dstDpid,
                                       boolean tunnelEnabled) {
         // Floodlight supports single path routing now
 
@@ -746,7 +753,7 @@ public class TopologyManager implements
                            FloodlightContext cntx) {
         switch (msg.getType()) {
             case PACKET_IN:
-                ctrIncoming.updateCounterNoFlush();
+                ctrIncoming.increment();
                 return this.processPacketInMessage(sw,
                                                    (OFPacketIn) msg, cntx);
             default:
@@ -762,10 +769,10 @@ public class TopologyManager implements
 
     private class HAListenerDelegate implements IHAListener {
         @Override
-        public void transitionToMaster() {
-            role = Role.MASTER;
+        public void transitionToActive() {
+            role = HARole.ACTIVE;
             log.debug("Re-computing topology due " +
-                    "to HA change from SLAVE->MASTER");
+                    "to HA change from STANDBY->ACTIVE");
             newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS,
                                        TimeUnit.MILLISECONDS);
         }
@@ -796,6 +803,12 @@ public class TopologyManager implements
             // TODO Auto-generated method stub
             return false;
         }
+
+		@Override
+		public void transitionToStandby() {
+			// TODO Auto-generated method stub
+			
+		}
     }
 
     // *****************
@@ -832,6 +845,7 @@ public class TopologyManager implements
         l.add(ILinkDiscoveryService.class);
         l.add(IThreadPoolService.class);
         l.add(IFloodlightProviderService.class);
+        l.add(IOFSwitchService.class);
         l.add(ICounterStoreService.class);
         l.add(IRestApiService.class);
         return l;
@@ -844,11 +858,12 @@ public class TopologyManager implements
         threadPool = context.getServiceImpl(IThreadPoolService.class);
         floodlightProvider =
                 context.getServiceImpl(IFloodlightProviderService.class);
+        switchService = context.getServiceImpl(IOFSwitchService.class);
         restApi = context.getServiceImpl(IRestApiService.class);
         debugCounters = context.getServiceImpl(IDebugCounterService.class);
         debugEvents = context.getServiceImpl(IDebugEventService.class);
 
-        switchPorts = new HashMap<Long,Set<Short>>();
+        switchPorts = new HashMap<DatapathId, Set<OFPort>>();
         switchPortLinks = new HashMap<NodePortTuple, Set<Link>>();
         directLinks = new HashMap<NodePortTuple, Set<Link>>();
         portBroadcastDomainLinks = new HashMap<NodePortTuple, Set<Link>>();
@@ -884,7 +899,7 @@ public class TopologyManager implements
         ScheduledExecutorService ses = threadPool.getScheduledExecutor();
         newInstanceTask = new SingletonTask(ses, new UpdateTopologyWorker());
 
-        if (role != Role.SLAVE)
+        if (role != HARole.STANDBY)
             newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS,
                                    TimeUnit.MILLISECONDS);
 
@@ -924,17 +939,17 @@ public class TopologyManager implements
      * @param cntx
      * @return
      */
-    protected Command dropFilter(long sw, OFPacketIn pi,
+    protected Command dropFilter(DatapathId sw, OFPacketIn pi,
                                              FloodlightContext cntx) {
         Command result = Command.CONTINUE;
-        short port = pi.getInPort();
+        OFPort port = pi.getInPort();
 
         // If the input port is not allowed for data traffic, drop everything.
         // BDDP packets will not reach this stage.
         if (isAllowed(sw, port) == false) {
             if (log.isTraceEnabled()) {
                 log.trace("Ignoring packet because of topology " +
-                        "restriction on switch={}, port={}", sw, port);
+                        "restriction on switch={}, port={}", sw.getLong(), port.getPortNumber());
                 result = Command.STOP;
             }
         }
@@ -955,49 +970,45 @@ public class TopologyManager implements
             		"topology discovery packet",
             recommendation=LogMessageDoc.CHECK_SWITCH)
     public void doMultiActionPacketOut(byte[] packetData, IOFSwitch sw,
-                                       Set<Short> ports,
+                                       Set<OFPort> ports,
                                        FloodlightContext cntx) {
 
         if (ports == null) return;
         if (packetData == null || packetData.length <= 0) return;
 
-        OFPacketOut po =
-                (OFPacketOut) floodlightProvider.getOFMessageFactory().
-                getMessage(OFType.PACKET_OUT);
-
+        //OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT);
+        OFPacketOut.Builder pob = sw.getOFFactory().buildPacketOut();
         List<OFAction> actions = new ArrayList<OFAction>();
-        for(short p: ports) {
-            actions.add(new OFActionOutput(p, (short) 0));
+        for(OFPort p: ports) {
+            //actions.add(new OFActionOutput(p, (short) 0));
+            actions.add(sw.getOFFactory().actions().output(p, 0));
         }
 
         // set actions
-        po.setActions(actions);
+        pob.setActions(actions);
         // set action length
-        po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH *
-                ports.size()));
+        //po.setActionsLength((short) (OFActionOutput.MINIMUM_LENGTH * ports.size()));
         // set buffer-id to BUFFER_ID_NONE
-        po.setBufferId(OFPacketOut.BUFFER_ID_NONE);
+        pob.setBufferId(OFBufferId.NO_BUFFER);
         // set in-port to OFPP_NONE
-        po.setInPort(OFPort.OFPP_NONE.getValue());
+        pob.setInPort(OFPort.ZERO);
 
         // set packet data
-        po.setPacketData(packetData);
+        pob.setData(packetData);
 
         // compute and set packet length.
-        short poLength = (short)(OFPacketOut.MINIMUM_LENGTH +
-                po.getActionsLength() +
-                packetData.length);
+        //short poLength = (short)(OFPacketOut.MINIMUM_LENGTH + po.getActionsLength() + packetData.length);
 
-        po.setLength(poLength);
+        //po.setLength(poLength);
 
         try {
             //counterStore.updatePktOutFMCounterStore(sw, po);
             if (log.isTraceEnabled()) {
                 log.trace("write broadcast packet on switch-id={} " +
                         "interaces={} packet-data={} packet-out={}",
-                        new Object[] {sw.getId(), ports, packetData, po});
+                        new Object[] {sw.getId(), ports, packetData, pob.build()});
             }
-            sw.write(po, cntx);
+            sw.write(pob.build(), LogicalOFMessageCategory.MAIN);
 
         } catch (IOException e) {
             log.error("Failure writing packet out", e);
@@ -1012,11 +1023,11 @@ public class TopologyManager implements
      * @param sid
      * @return
      */
-    protected Set<Short> getPortsToEliminateForBDDP(long sid) {
+    protected Set<OFPort> getPortsToEliminateForBDDP(DatapathId sid) {
         Set<NodePortTuple> suppressedNptList = linkDiscovery.getSuppressLLDPsInfo();
         if (suppressedNptList == null) return null;
 
-        Set<Short> resultPorts = new HashSet<Short>();
+        Set<OFPort> resultPorts = new HashSet<OFPort>();
         for(NodePortTuple npt: suppressedNptList) {
             if (npt.getNodeId() == sid) {
                 resultPorts.add(npt.getPortId());
@@ -1035,36 +1046,36 @@ public class TopologyManager implements
      * @param pi
      * @param cntx
      */
-    protected void doFloodBDDP(long pinSwitch, OFPacketIn pi,
+    protected void doFloodBDDP(DatapathId pinSwitch, OFPacketIn pi,
                                FloodlightContext cntx) {
 
         TopologyInstance ti = getCurrentInstance(false);
 
-        Set<Long> switches = ti.getSwitchesInOpenflowDomain(pinSwitch);
+        Set<DatapathId> switches = ti.getSwitchesInOpenflowDomain(pinSwitch);
 
         if (switches == null)
         {
             // indicates no links are connected to the switches
-            switches = new HashSet<Long>();
+            switches = new HashSet<DatapathId>();
             switches.add(pinSwitch);
         }
 
-        for(long sid: switches) {
-            IOFSwitch sw = floodlightProvider.getSwitch(sid);
+        for(DatapathId sid: switches) {
+            IOFSwitch sw = switchService.getSwitch(sid);
             if (sw == null) continue;
-            Collection<Short> enabledPorts = sw.getEnabledPortNumbers();
+            Collection<OFPort> enabledPorts = sw.getEnabledPortNumbers();
             if (enabledPorts == null)
                 continue;
-            Set<Short> ports = new HashSet<Short>();
+            Set<OFPort> ports = new HashSet<OFPort>();
             ports.addAll(enabledPorts);
 
             // all the ports known to topology // without tunnels.
             // out of these, we need to choose only those that are
             // broadcast port, otherwise, we should eliminate.
-            Set<Short> portsKnownToTopo = ti.getPortsWithLinks(sid);
+            Set<OFPort> portsKnownToTopo = ti.getPortsWithLinks(sid);
 
             if (portsKnownToTopo != null) {
-                for(short p: portsKnownToTopo) {
+                for(OFPort p: portsKnownToTopo) {
                     NodePortTuple npt =
                             new NodePortTuple(sid, p);
                     if (ti.isBroadcastDomainPort(npt) == false) {
@@ -1073,7 +1084,7 @@ public class TopologyManager implements
                 }
             }
 
-            Set<Short> portsToEliminate = getPortsToEliminateForBDDP(sid);
+            Set<OFPort> portsToEliminate = getPortsToEliminateForBDDP(sid);
             if (portsToEliminate != null) {
                 ports.removeAll(portsToEliminate);
             }
@@ -1084,7 +1095,7 @@ public class TopologyManager implements
             }
 
             // we have all the switch ports to which we need to broadcast.
-            doMultiActionPacketOut(pi.getPacketData(), sw, ports, cntx);
+            doMultiActionPacketOut(pi.getData(), sw, ports, cntx);
         }
 
     }
@@ -1168,18 +1179,18 @@ public class TopologyManager implements
         return (Collections.unmodifiableList(appliedUpdates));
     }
 
-    protected void addOrUpdateSwitch(long sw) {
+    protected void addOrUpdateSwitch(DatapathId sw) {
         // nothing to do here for the time being.
         return;
     }
 
-    public void addTunnelPort(long sw, short port) {
+    public void addTunnelPort(DatapathId sw, OFPort port) {
         NodePortTuple npt = new NodePortTuple(sw, port);
         tunnelPorts.add(npt);
         tunnelPortsUpdated = true;
     }
 
-    public void removeTunnelPort(long sw, short port) {
+    public void removeTunnelPort(DatapathId sw, OFPort port) {
         NodePortTuple npt = new NodePortTuple(sw, port);
         tunnelPorts.remove(npt);
         tunnelPortsUpdated = true;
@@ -1248,7 +1259,7 @@ public class TopologyManager implements
 
         TopologyEventInfo topologyInfo =
                 new TopologyEventInfo(0, nt.getClusters().size(),
-                                      new HashMap<Long, List<NodePortTuple>>(),
+                                      new HashMap<DatapathId, List<NodePortTuple>>(),
                                       0);
         evTopology.updateEventWithFlush(new TopologyEvent(reason,
                                                           topologyInfo));
@@ -1318,27 +1329,27 @@ public class TopologyManager implements
 
     public void informListeners(List<LDUpdate> linkUpdates) {
 
-        if (role != null && role != Role.MASTER)
+        if (role != null && role != HARole.ACTIVE)
             return;
 
-        for(int i=0; i<topologyAware.size(); ++i) {
+        for(int i=0; i < topologyAware.size(); ++i) {
             ITopologyListener listener = topologyAware.get(i);
             listener.topologyChanged(linkUpdates);
         }
     }
 
-    public void addSwitch(long sid) {
+    public void addSwitch(DatapathId sid) {
         if (switchPorts.containsKey(sid) == false) {
-            switchPorts.put(sid, new HashSet<Short>());
+            switchPorts.put(sid, new HashSet<OFPort>());
         }
     }
 
-    private void addPortToSwitch(long s, short p) {
+    private void addPortToSwitch(DatapathId s, OFPort p) {
         addSwitch(s);
         switchPorts.get(s).add(p);
     }
 
-    public void removeSwitch(long sid) {
+    public void removeSwitch(DatapathId sid) {
         // Delete all the links in the switch, switch and all
         // associated data should be deleted.
         if (switchPorts.containsKey(sid) == false) return;
@@ -1351,7 +1362,7 @@ public class TopologyManager implements
         }
 
         Set<Link> linksToRemove = new HashSet<Link>();
-        for(Short p: switchPorts.get(sid)) {
+        for(OFPort p: switchPorts.get(sid)) {
             NodePortTuple n1 = new NodePortTuple(sid, p);
             linksToRemove.addAll(switchPortLinks.get(n1));
         }
@@ -1414,13 +1425,13 @@ public class TopologyManager implements
         return result1 || result2;
     }
 
-    protected void addOrUpdateTunnelLink(long srcId, short srcPort, long dstId,
-                                    short dstPort) {
+    protected void addOrUpdateTunnelLink(DatapathId srcId, OFPort srcPort, DatapathId dstId,
+                                    OFPort dstPort) {
         // If you need to handle tunnel links, this is a placeholder.
     }
 
-    public void addOrUpdateLink(long srcId, short srcPort, long dstId,
-                                short dstPort, LinkType type) {
+    public void addOrUpdateLink(DatapathId srcId, OFPort srcPort, DatapathId dstId,
+                                OFPort dstPort, LinkType type) {
         Link link = new Link(srcId, srcPort, dstId, dstPort);
 
         if (type.equals(LinkType.MULTIHOP_LINK)) {
@@ -1477,8 +1488,8 @@ public class TopologyManager implements
         }
     }
 
-    public void removeLink(long srcId, short srcPort,
-                           long dstId, short dstPort) {
+    public void removeLink(DatapathId srcId, OFPort srcPort,
+    		DatapathId dstId, OFPort dstPort) {
         Link link = new Link(srcId, srcPort, dstId, dstPort);
         removeLink(link);
     }
@@ -1507,7 +1518,7 @@ public class TopologyManager implements
     /**
      * Getters.  No Setters.
      */
-    public Map<Long, Set<Short>> getSwitchPorts() {
+    public Map<DatapathId, Set<OFPort>> getSwitchPorts() {
         return switchPorts;
     }
 
@@ -1533,15 +1544,15 @@ public class TopologyManager implements
      *  Switch methods
      */
     @Override
-    public Set<Short> getPorts(long sw) {
-        IOFSwitch iofSwitch = floodlightProvider.getSwitch(sw);
+    public Set<OFPort> getPorts(DatapathId sw) {
+        IOFSwitch iofSwitch = switchService.getSwitch(sw);
         if (iofSwitch == null) return Collections.emptySet();
 
-        Collection<Short> ofpList = iofSwitch.getEnabledPortNumbers();
+        Collection<OFPort> ofpList = iofSwitch.getEnabledPortNumbers();
         if (ofpList == null) return Collections.emptySet();
 
-        Set<Short> ports = new HashSet<Short>(ofpList);
-        Set<Short> qPorts = linkDiscovery.getQuarantinedPorts(sw);
+        Set<OFPort> ports = new HashSet<OFPort>(ofpList);
+        Set<OFPort> qPorts = linkDiscovery.getQuarantinedPorts(sw);
         if (qPorts != null)
             ports.removeAll(qPorts);
 
diff --git a/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java b/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java
index 75b0b00d3..eb4c368e8 100644
--- a/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java
+++ b/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java
@@ -22,9 +22,10 @@ import java.util.Set;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.LogicalOFMessageCategory;
 
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFType;
 
 /**
  * Dampens OFMessages sent to an OF switch. A message is only written to 
@@ -134,7 +135,7 @@ public class OFMessageDamper {
                         FloodlightContext cntx, boolean flush) 
             throws IOException {
         if (! msgTypesToCache.contains(msg.getType())) {
-            sw.writeThrottled(msg, cntx);
+            sw.write(msg, LogicalOFMessageCategory.MAIN);
             if (flush) {
                 sw.flush();
             }
@@ -146,7 +147,7 @@ public class OFMessageDamper {
             // entry exists in cache. Dampening.
             return false; 
         } else {
-            sw.writeThrottled(msg, cntx);
+            sw.write(msg, LogicalOFMessageCategory.MAIN);
             if (flush) {
                 sw.flush();
             }
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java b/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java
index 1d64144dc..258368329 100644
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java
+++ b/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java
@@ -28,14 +28,14 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-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.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFMatch;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketOut;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/org/openflow/protocol/Instantiable.java b/src/main/java/org/openflow/protocol/Instantiable.java
deleted file mode 100644
index 1358ba752..000000000
--- a/src/main/java/org/openflow/protocol/Instantiable.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public interface Instantiable<E> {
-
-    /**
-     * Create a new instance of a given subclass.
-     * @return the new instance.
-     */
-    public E instantiate();
-}
diff --git a/src/main/java/org/openflow/protocol/OFBarrierReply.java b/src/main/java/org/openflow/protocol/OFBarrierReply.java
deleted file mode 100644
index a79a15f07..000000000
--- a/src/main/java/org/openflow/protocol/OFBarrierReply.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.util.U16;
-
-/**
- * Represents an OFPT_BARRIER_REPLY message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFBarrierReply extends OFMessage {
-    public OFBarrierReply() {
-        super();
-        this.type = OFType.BARRIER_REPLY;
-        this.length = U16.t(OFMessage.MINIMUM_LENGTH);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFBarrierRequest.java b/src/main/java/org/openflow/protocol/OFBarrierRequest.java
deleted file mode 100644
index 999218636..000000000
--- a/src/main/java/org/openflow/protocol/OFBarrierRequest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.util.U16;
-
-/**
- * Represents an OFPT_BARRIER_REQUEST message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFBarrierRequest extends OFMessage {
-    public OFBarrierRequest() {
-        super();
-        this.type = OFType.BARRIER_REQUEST;
-        this.length = U16.t(OFMessage.MINIMUM_LENGTH);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFEchoReply.java b/src/main/java/org/openflow/protocol/OFEchoReply.java
deleted file mode 100644
index 3e282a74a..000000000
--- a/src/main/java/org/openflow/protocol/OFEchoReply.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_echo_reply message
- * 
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- */
-
-public class OFEchoReply extends OFEchoRequest {
-    public static int MINIMUM_LENGTH = 8;
-
-    public OFEchoReply() {
-        super();
-        this.type = OFType.ECHO_REPLY;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFEchoRequest.java b/src/main/java/org/openflow/protocol/OFEchoRequest.java
deleted file mode 100644
index 295a3972e..000000000
--- a/src/main/java/org/openflow/protocol/OFEchoRequest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-
-import java.util.Arrays;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_echo_request message
- * 
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- */
-
-public class OFEchoRequest extends OFMessage {
-    public static int MINIMUM_LENGTH = 8;
-    byte[] payload;
-
-    public OFEchoRequest() {
-        super();
-        this.type = OFType.ECHO_REQUEST;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer bb) {
-        super.readFrom(bb);
-        int datalen = this.getLengthU() - MINIMUM_LENGTH;
-        if (datalen > 0) {
-            this.payload = new byte[datalen];
-            bb.readBytes(payload);
-        }
-    }
-
-    /**
-     * @return the payload
-     */
-    public byte[] getPayload() {
-        return payload;
-    }
-
-    /**
-     * @param payload
-     *            the payload to set
-     */
-    public void setPayload(byte[] payload) {
-        this.payload = payload;
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer bb) {
-        super.writeTo(bb);
-        if (payload != null)
-            bb.writeBytes(payload);
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = super.hashCode();
-        result = prime * result + Arrays.hashCode(payload);
-        return result;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (!super.equals(obj))
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        OFEchoRequest other = (OFEchoRequest) obj;
-        if (!Arrays.equals(payload, other.payload))
-            return false;
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFError.java b/src/main/java/org/openflow/protocol/OFError.java
deleted file mode 100644
index df7b23602..000000000
--- a/src/main/java/org/openflow/protocol/OFError.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.factory.MessageParseException;
-import org.openflow.protocol.factory.OFMessageFactory;
-import org.openflow.protocol.factory.OFMessageFactoryAware;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_error_msg
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- */
-public class OFError extends OFMessage implements OFMessageFactoryAware {
-    public static int MINIMUM_LENGTH = 12;
-
-    public enum OFErrorType {
-        // OFPET_VENDOR_ERROR is an extension that was added in Open vSwitch and isn't
-        // in the OF 1.0 spec, but it was easier to add it here instead of adding
-        // generic support for extensible vendor-defined error messages.
-        // It uses the random value 0xb0c2 to avoid conflicts with other possible new
-        // error types. Support for vendor-defined extended errors has been standardized
-        // in the OF 1.2 spec, so this workaround is only needed for 1.0.
-        OFPET_HELLO_FAILED, OFPET_BAD_REQUEST, OFPET_BAD_ACTION, OFPET_FLOW_MOD_FAILED, OFPET_PORT_MOD_FAILED, OFPET_QUEUE_OP_FAILED, OFPET_VENDOR_ERROR((short)0xb0c2);
-
-        protected short value;
-
-        private OFErrorType() {
-            this.value = (short) this.ordinal();
-        }
-
-        private OFErrorType(short value) {
-            this.value = value;
-        }
-
-        public short getValue() {
-            return value;
-        }
-    }
-
-    public enum OFHelloFailedCode {
-        OFPHFC_INCOMPATIBLE, OFPHFC_EPERM
-    }
-
-    public enum OFBadRequestCode {
-        OFPBRC_BAD_VERSION, OFPBRC_BAD_TYPE, OFPBRC_BAD_STAT, OFPBRC_BAD_VENDOR, OFPBRC_BAD_SUBTYPE, OFPBRC_EPERM, OFPBRC_BAD_LEN, OFPBRC_BUFFER_EMPTY, OFPBRC_BUFFER_UNKNOWN
-    }
-
-    public enum OFBadActionCode {
-        OFPBAC_BAD_TYPE, OFPBAC_BAD_LEN, OFPBAC_BAD_VENDOR, OFPBAC_BAD_VENDOR_TYPE, OFPBAC_BAD_OUT_PORT, OFPBAC_BAD_ARGUMENT, OFPBAC_EPERM, OFPBAC_TOO_MANY, OFPBAC_BAD_QUEUE
-    }
-
-    public enum OFFlowModFailedCode {
-        OFPFMFC_ALL_TABLES_FULL, OFPFMFC_OVERLAP, OFPFMFC_EPERM, OFPFMFC_BAD_EMERG_TIMEOUT, OFPFMFC_BAD_COMMAND, OFPFMFC_UNSUPPORTED
-    }
-
-    public enum OFPortModFailedCode {
-        OFPPMFC_BAD_PORT, OFPPMFC_BAD_HW_ADDR
-    }
-
-    public enum OFQueueOpFailedCode {
-        OFPQOFC_BAD_PORT, OFPQOFC_BAD_QUEUE, OFPQOFC_EPERM
-    }
-
-    protected short errorType;
-    protected short errorCode;
-    protected int vendor;
-    protected int vendorErrorType;
-    protected short vendorErrorCode;
-    protected OFMessageFactory factory;
-    protected byte[] error;
-    protected boolean errorIsAscii;
-
-    public OFError() {
-        super();
-        this.type = OFType.ERROR;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /** convenience constructor */
-    public OFError(OFErrorType errorType) {
-        this();
-        setErrorType(errorType);
-    }
-
-    /**
-     * @return the errorType
-     */
-    public short getErrorType() {
-        return errorType;
-    }
-
-    /**
-     * @param errorType
-     *            the errorType to set
-     */
-    public void setErrorType(short errorType) {
-        this.errorType = errorType;
-    }
-
-    public void setErrorType(OFErrorType type) {
-        this.errorType = type.getValue();
-    }
-
-    /**
-     * @return true if the error is an extended vendor error
-     */
-    public boolean isVendorError() {
-        return errorType == OFErrorType.OFPET_VENDOR_ERROR.getValue();
-    }
-
-    /**
-     * @return the errorCode
-     */
-    public short getErrorCode() {
-        return errorCode;
-    }
-
-    /**
-     * @param errorCode
-     *            the errorCode to set
-     */
-    public void setErrorCode(OFHelloFailedCode code) {
-        this.errorCode = (short) code.ordinal();
-    }
-
-    public void setErrorCode(short errorCode) {
-        this.errorCode = errorCode;
-    }
-
-    public void setErrorCode(OFBadRequestCode code) {
-        this.errorCode = (short) code.ordinal();
-    }
-
-    public void setErrorCode(OFBadActionCode code) {
-        this.errorCode = (short) code.ordinal();
-    }
-
-    public void setErrorCode(OFFlowModFailedCode code) {
-        this.errorCode = (short) code.ordinal();
-    }
-
-    public void setErrorCode(OFPortModFailedCode code) {
-        this.errorCode = (short) code.ordinal();
-    }
-
-    public void setErrorCode(OFQueueOpFailedCode code) {
-        this.errorCode = (short) code.ordinal();
-    }
-
-    public int getVendorErrorType() {
-        return vendorErrorType;
-    }
-
-    public void setVendorErrorType(int vendorErrorType) {
-        this.vendorErrorType = vendorErrorType;
-    }
-
-    public short getVendorErrorCode() {
-        return vendorErrorCode;
-    }
-
-    public void setVendorErrorCode(short vendorErrorCode) {
-        this.vendorErrorCode = vendorErrorCode;
-    }
-
-    public OFMessage getOffendingMsg() throws MessageParseException {
-        // should only have one message embedded; if more than one, just
-        // grab first
-        if (this.error == null)
-            return null;
-        ChannelBuffer errorMsg = ChannelBuffers.wrappedBuffer(this.error);
-        if (factory == null)
-            throw new RuntimeException("MessageFactory not set");
-
-        List<OFMessage> msglist = this.factory.parseMessage(errorMsg);
-        if (msglist == null)
-                return null;
-        return msglist.get(0);
-    }
-
-    /**
-     * Write this offending message into the payload of the Error message
-     *
-     * @param offendingMsg
-     */
-
-    public void setOffendingMsg(OFMessage offendingMsg) {
-        if (offendingMsg == null) {
-            super.setLengthU(MINIMUM_LENGTH);
-        } else {
-            this.error = new byte[offendingMsg.getLengthU()];
-            ChannelBuffer data = ChannelBuffers.wrappedBuffer(this.error);
-            data.writerIndex(0);
-            offendingMsg.writeTo(data);
-            super.setLengthU(MINIMUM_LENGTH + offendingMsg.getLengthU());
-        }
-    }
-
-    public OFMessageFactory getFactory() {
-        return factory;
-    }
-
-    @Override
-    public void setMessageFactory(OFMessageFactory factory) {
-        this.factory = factory;
-    }
-
-    /**
-     * @return the error
-     */
-    public byte[] getError() {
-        return error;
-    }
-
-    /**
-     * @param error
-     *            the error to set
-     */
-    public void setError(byte[] error) {
-        this.error = error;
-    }
-
-    /**
-     * @return the errorIsAscii
-     */
-    public boolean isErrorIsAscii() {
-        return errorIsAscii;
-    }
-
-    /**
-     * @param errorIsAscii
-     *            the errorIsAscii to set
-     */
-    public void setErrorIsAscii(boolean errorIsAscii) {
-        this.errorIsAscii = errorIsAscii;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.errorType = data.readShort();
-        this.errorCode = data.readShort();
-        int dataLength = this.getLengthU() - MINIMUM_LENGTH;
-        if (dataLength > 0) {
-            this.error = new byte[dataLength];
-            data.readBytes(this.error);
-            if (this.errorType == OFErrorType.OFPET_HELLO_FAILED.getValue())
-                this.errorIsAscii = true;
-        }
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(errorType);
-        data.writeShort(errorCode);
-        if (error != null)
-            data.writeBytes(error);
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = super.hashCode();
-        result = prime * result + Arrays.hashCode(error);
-        result = prime * result + errorCode;
-        result = prime * result + (errorIsAscii ? 1231 : 1237);
-        result = prime * result + errorType;
-        return result;
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (!super.equals(obj))
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        OFError other = (OFError) obj;
-        if (!Arrays.equals(error, other.error))
-            return false;
-        if (errorCode != other.errorCode)
-            return false;
-        if (errorIsAscii != other.errorIsAscii)
-            return false;
-        if (errorType != other.errorType)
-            return false;
-        return true;
-    }
-
-}
diff --git a/src/main/java/org/openflow/protocol/OFFeaturesReply.java b/src/main/java/org/openflow/protocol/OFFeaturesReply.java
deleted file mode 100644
index 7c2cc51cf..000000000
--- a/src/main/java/org/openflow/protocol/OFFeaturesReply.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.serializers.OFFeaturesReplyJSONSerializer;
-import org.openflow.protocol.serializers.StringDpidToLongJSONDeserializer;
-import org.openflow.util.U16;
-
-
-/**
- * Represents a features reply message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- *
- */
-@JsonSerialize(using=OFFeaturesReplyJSONSerializer.class)
-public class OFFeaturesReply extends OFMessage {
-    public static int MINIMUM_LENGTH = 32;
-
-    /**
-     * Corresponds to bits on the capabilities field
-     */
-    public enum OFCapabilities {
-        OFPC_FLOW_STATS     (1 << 0),
-        OFPC_TABLE_STATS    (1 << 1),
-        OFPC_PORT_STATS     (1 << 2),
-        OFPC_STP            (1 << 3),
-        OFPC_RESERVED       (1 << 4),
-        OFPC_IP_REASM       (1 << 5),
-        OFPC_QUEUE_STATS    (1 << 6),
-        OFPC_ARP_MATCH_IP   (1 << 7);
-
-        protected int value;
-
-        private OFCapabilities(int value) {
-            this.value = value;
-        }
-
-        /**
-         * @return the value
-         */
-        public int getValue() {
-            return value;
-        }
-    }
-
-    protected long datapathId;
-    protected int buffers;
-    protected byte tables;
-    protected int capabilities;
-    protected int actions;
-    protected List<OFPhysicalPort> ports;
-
-    public OFFeaturesReply() {
-        super();
-        this.type = OFType.FEATURES_REPLY;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /**
-     * @return the datapathId
-     */
-    public long getDatapathId() {
-        return datapathId;
-    }
-
-    /**
-     * @param datapathId the datapathId to set
-     */
-    @JsonDeserialize(using=StringDpidToLongJSONDeserializer.class)
-    public void setDatapathId(long datapathId) {
-        this.datapathId = datapathId;
-    }
-
-    /**
-     * @return the buffers
-     */
-    public int getBuffers() {
-        return buffers;
-    }
-
-    /**
-     * @param buffers the buffers to set
-     */
-    public void setBuffers(int buffers) {
-        this.buffers = buffers;
-    }
-
-    /**
-     * @return the tables
-     */
-    public byte getTables() {
-        return tables;
-    }
-
-    /**
-     * @param tables the tables to set
-     */
-    public void setTables(byte tables) {
-        this.tables = tables;
-    }
-
-    /**
-     * @return the capabilities
-     */
-    public int getCapabilities() {
-        return capabilities;
-    }
-
-    /**
-     * @param capabilities the capabilities to set
-     */
-    public void setCapabilities(int capabilities) {
-        this.capabilities = capabilities;
-    }
-
-    /**
-     * @return the actions
-     */
-    public int getActions() {
-        return actions;
-    }
-
-    /**
-     * @param actions the actions to set
-     */
-    public void setActions(int actions) {
-        this.actions = actions;
-    }
-
-    /**
-     * @return the ports
-     */
-    public List<OFPhysicalPort> getPorts() {
-        return ports;
-    }
-
-    /**
-     * @param ports the ports to set
-     */
-    public void setPorts(List<OFPhysicalPort> ports) {
-        this.ports = ports;
-        if (ports == null) {
-            this.setLengthU(MINIMUM_LENGTH);
-        } else {
-            this.setLengthU(MINIMUM_LENGTH + ports.size()
-                    * OFPhysicalPort.MINIMUM_LENGTH);
-        }
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.datapathId = data.readLong();
-        this.buffers = data.readInt();
-        this.tables = data.readByte();
-        data.readerIndex(data.readerIndex() + 3); // pad
-        this.capabilities = data.readInt();
-        this.actions = data.readInt();
-        if (this.ports == null) {
-            this.ports = new ArrayList<OFPhysicalPort>();
-        } else {
-            this.ports.clear();
-        }
-        int portCount = (super.getLengthU() - 32)
-                / OFPhysicalPort.MINIMUM_LENGTH;
-        OFPhysicalPort port;
-        for (int i = 0; i < portCount; ++i) {
-            port = new OFPhysicalPort();
-            port.readFrom(data);
-            this.ports.add(port);
-        }
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeLong(this.datapathId);
-        data.writeInt(this.buffers);
-        data.writeByte(this.tables);
-        data.writeShort((short) 0); // pad
-        data.writeByte((byte) 0); // pad
-        data.writeInt(this.capabilities);
-        data.writeInt(this.actions);
-        if (this.ports != null)
-            for (OFPhysicalPort port : this.ports) {
-                port.writeTo(data);
-            }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 139;
-        int result = super.hashCode();
-        result = prime * result + actions;
-        result = prime * result + buffers;
-        result = prime * result + capabilities;
-        result = prime * result + (int) (datapathId ^ (datapathId >>> 32));
-        result = prime * result + ((ports == null) ? 0 : ports.hashCode());
-        result = prime * result + tables;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFFeaturesReply)) {
-            return false;
-        }
-        OFFeaturesReply other = (OFFeaturesReply) obj;
-        if (actions != other.actions) {
-            return false;
-        }
-        if (buffers != other.buffers) {
-            return false;
-        }
-        if (capabilities != other.capabilities) {
-            return false;
-        }
-        if (datapathId != other.datapathId) {
-            return false;
-        }
-        if (ports == null) {
-            if (other.ports != null) {
-                return false;
-            }
-        } else if (!ports.equals(other.ports)) {
-            return false;
-        }
-        if (tables != other.tables) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFFeaturesRequest.java b/src/main/java/org/openflow/protocol/OFFeaturesRequest.java
deleted file mode 100644
index 0a89e4f57..000000000
--- a/src/main/java/org/openflow/protocol/OFFeaturesRequest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.util.U16;
-
-
-/**
- * Represents a features request message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- *
- */
-public class OFFeaturesRequest extends OFMessage {
-    public static int MINIMUM_LENGTH = 8;
-
-    public OFFeaturesRequest() {
-        super();
-        this.type = OFType.FEATURES_REQUEST;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFFlowMod.java b/src/main/java/org/openflow/protocol/OFFlowMod.java
deleted file mode 100644
index 0d2aad215..000000000
--- a/src/main/java/org/openflow/protocol/OFFlowMod.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.factory.OFActionFactory;
-import org.openflow.protocol.factory.OFActionFactoryAware;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_flow_mod message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- *
- */
-public class OFFlowMod extends OFMessage implements OFActionFactoryAware, Cloneable {
-    public static int MINIMUM_LENGTH = 72;
-
-    public static final short OFPFC_ADD = 0;                /* New flow. */
-    public static final short OFPFC_MODIFY = 1;             /* Modify all matching flows. */
-    public static final short OFPFC_MODIFY_STRICT = 2;      /* Modify entry strictly matching wildcards */
-    public static final short OFPFC_DELETE=3;               /* Delete all matching flows. */
-    public static final short OFPFC_DELETE_STRICT =4;       /* Strictly match wildcards and priority. */
-
-    // Open Flow Flow Mod Flags. Use "or" operation to set multiple flags
-    public static final short OFPFF_SEND_FLOW_REM = 0x1; // 1 << 0
-    public static final short OFPFF_CHECK_OVERLAP = 0x2; // 1 << 1
-    public static final short OFPFF_EMERG         = 0x4; // 1 << 2
-
-    protected OFActionFactory actionFactory;
-    protected OFMatch match;
-    protected long cookie;
-    protected short command;
-    protected short idleTimeout;
-    protected short hardTimeout;
-    protected short priority;
-    protected int bufferId;
-    protected short outPort;
-    protected short flags;
-    protected List<OFAction> actions;
-
-    public OFFlowMod() {
-        super();
-        this.outPort = OFPort.OFPP_NONE.getValue();
-        this.type = OFType.FLOW_MOD;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /**
-     * Get buffer_id
-     * @return
-     */
-    public int getBufferId() {
-        return this.bufferId;
-    }
-
-    /**
-     * Set buffer_id
-     * @param bufferId
-     */
-    public OFFlowMod setBufferId(int bufferId) {
-        this.bufferId = bufferId;
-        return this;
-    }
-
-    /**
-     * Get cookie
-     * @return
-     */
-    public long getCookie() {
-        return this.cookie;
-    }
-
-    /**
-     * Set cookie
-     * @param cookie
-     */
-    public OFFlowMod setCookie(long cookie) {
-        this.cookie = cookie;
-        return this;
-    }
-
-    /**
-     * Get command
-     * @return
-     */
-    public short getCommand() {
-        return this.command;
-    }
-
-    /**
-     * Set command
-     * @param command
-     */
-    public OFFlowMod setCommand(short command) {
-        this.command = command;
-        return this;
-    }
-
-    /**
-     * Get flags
-     * @return
-     */
-    public short getFlags() {
-        return this.flags;
-    }
-
-    /**
-     * Set flags
-     * @param flags
-     */
-    public OFFlowMod setFlags(short flags) {
-        this.flags = flags;
-        return this;
-    }
-
-    /**
-     * Get hard_timeout
-     * @return
-     */
-    public short getHardTimeout() {
-        return this.hardTimeout;
-    }
-
-    /**
-     * Set hard_timeout
-     * @param hardTimeout
-     */
-    public OFFlowMod setHardTimeout(short hardTimeout) {
-        this.hardTimeout = hardTimeout;
-        return this;
-    }
-
-    /**
-     * Get idle_timeout
-     * @return
-     */
-    public short getIdleTimeout() {
-        return this.idleTimeout;
-    }
-
-    /**
-     * Set idle_timeout
-     * @param idleTimeout
-     */
-    public OFFlowMod setIdleTimeout(short idleTimeout) {
-        this.idleTimeout = idleTimeout;
-        return this;
-    }
-
-    /**
-     * Gets a copy of the OFMatch object for this FlowMod, changes to this
-     * object do not modify the FlowMod
-     * @return
-     */
-    public OFMatch getMatch() {
-        return this.match;
-    }
-
-    /**
-     * Set match
-     * @param match
-     */
-    public OFFlowMod setMatch(OFMatch match) {
-        this.match = match;
-        return this;
-    }
-
-    /**
-     * Get out_port
-     * @return
-     */
-    public short getOutPort() {
-        return this.outPort;
-    }
-
-    /**
-     * Set out_port
-     * @param outPort
-     */
-    public OFFlowMod setOutPort(short outPort) {
-        this.outPort = outPort;
-        return this;
-    }
-
-    /**
-     * Set out_port
-     * @param port
-     */
-    public OFFlowMod setOutPort(OFPort port) {
-        this.outPort = port.getValue();
-        return this;
-    }
-
-    /**
-     * Get priority
-     * @return
-     */
-    public short getPriority() {
-        return this.priority;
-    }
-
-    /**
-     * Set priority
-     * @param priority
-     */
-    public OFFlowMod setPriority(short priority) {
-        this.priority = priority;
-        return this;
-    }
-
-    /**
-     * Returns read-only copies of the actions contained in this Flow Mod
-     * @return a list of ordered OFAction objects
-     */
-    public List<OFAction> getActions() {
-        return this.actions;
-    }
-
-    /**
-     * Sets the list of actions this Flow Mod contains
-     * @param actions a list of ordered OFAction objects
-     */
-    public OFFlowMod setActions(List<OFAction> actions) {
-        this.actions = actions;
-        return this;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        if (this.match == null)
-            this.match = new OFMatch();
-        this.match.readFrom(data);
-        this.cookie = data.readLong();
-        this.command = data.readShort();
-        this.idleTimeout = data.readShort();
-        this.hardTimeout = data.readShort();
-        this.priority = data.readShort();
-        this.bufferId = data.readInt();
-        this.outPort = data.readShort();
-        this.flags = data.readShort();
-        if (this.actionFactory == null)
-            throw new RuntimeException("OFActionFactory not set");
-        this.actions = this.actionFactory.parseActions(data, getLengthU() -
-                MINIMUM_LENGTH);
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        this.match.writeTo(data);
-        data.writeLong(cookie);
-        data.writeShort(command);
-        data.writeShort(idleTimeout);
-        data.writeShort(hardTimeout);
-        data.writeShort(priority);
-        data.writeInt(bufferId);
-        data.writeShort(outPort);
-        data.writeShort(flags);
-        if (actions != null) {
-            for (OFAction action : actions) {
-                action.writeTo(data);
-            }
-        }
-    }
-
-    @Override
-    public void setActionFactory(OFActionFactory actionFactory) {
-        this.actionFactory = actionFactory;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 227;
-        int result = super.hashCode();
-        result = prime * result + ((actions == null) ? 0 : actions.hashCode());
-        result = prime * result + bufferId;
-        result = prime * result + command;
-        result = prime * result + (int) (cookie ^ (cookie >>> 32));
-        result = prime * result + flags;
-        result = prime * result + hardTimeout;
-        result = prime * result + idleTimeout;
-        result = prime * result + ((match == null) ? 0 : match.hashCode());
-        result = prime * result + outPort;
-        result = prime * result + priority;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFFlowMod)) {
-            return false;
-        }
-        OFFlowMod other = (OFFlowMod) obj;
-        if (actions == null) {
-            if (other.actions != null) {
-                return false;
-            }
-        } else if (!actions.equals(other.actions)) {
-            return false;
-        }
-        if (bufferId != other.bufferId) {
-            return false;
-        }
-        if (command != other.command) {
-            return false;
-        }
-        if (cookie != other.cookie) {
-            return false;
-        }
-        if (flags != other.flags) {
-            return false;
-        }
-        if (hardTimeout != other.hardTimeout) {
-            return false;
-        }
-        if (idleTimeout != other.idleTimeout) {
-            return false;
-        }
-        if (match == null) {
-            if (other.match != null) {
-                return false;
-            }
-        } else if (!match.equals(other.match)) {
-            return false;
-        }
-        if (outPort != other.outPort) {
-            return false;
-        }
-        if (priority != other.priority) {
-            return false;
-        }
-        return true;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#clone()
-     */
-    @Override
-    public OFFlowMod clone() throws CloneNotSupportedException {
-        OFMatch neoMatch = match.clone();
-        OFFlowMod flowMod= (OFFlowMod) super.clone();
-        flowMod.setMatch(neoMatch);
-        List<OFAction> neoActions = new LinkedList<OFAction>();
-        for(OFAction action: this.actions)
-            neoActions.add(action.clone());
-        flowMod.setActions(neoActions);
-        return flowMod;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "OFFlowMod [actionFactory=" + actionFactory + ", actions="
-                + actions + ", bufferId=" + bufferId + ", command=" + command
-                + ", cookie=" + Long.toHexString(cookie) + ", flags=" + flags + ", hardTimeout="
-                + hardTimeout + ", idleTimeout=" + idleTimeout + ", match="
-                + match + ", outPort=" + outPort + ", priority=" + priority
-                + ", length=" + length + ", type=" + type + ", version="
-                + version + ", xid=" + xid + "]";
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFFlowRemoved.java b/src/main/java/org/openflow/protocol/OFFlowRemoved.java
deleted file mode 100644
index cfe2e14ce..000000000
--- a/src/main/java/org/openflow/protocol/OFFlowRemoved.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_flow_removed message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- *
- */
-public class OFFlowRemoved extends OFMessage {
-    public static int MINIMUM_LENGTH = 88;
-
-    public enum OFFlowRemovedReason {
-        OFPRR_IDLE_TIMEOUT,
-        OFPRR_HARD_TIMEOUT,
-        OFPRR_DELETE
-    }
-
-    protected OFMatch match;
-    protected long cookie;
-    protected short priority;
-    protected OFFlowRemovedReason reason;
-    protected int durationSeconds;
-    protected int durationNanoseconds;
-    protected short idleTimeout;
-    protected long packetCount;
-    protected long byteCount;
-    
-    public OFFlowRemoved() {
-        super();
-        this.type = OFType.FLOW_REMOVED;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /**
-     * Get cookie
-     * @return
-     */
-    public long getCookie() {
-        return this.cookie;
-    }
-
-    /**
-     * Set cookie
-     * @param cookie
-     */
-    public void setCookie(long cookie) {
-        this.cookie = cookie;
-    }
-
-    /**
-     * Get idle_timeout
-     * @return
-     */
-    public short getIdleTimeout() {
-        return this.idleTimeout;
-    }
-
-    /**
-     * Set idle_timeout
-     * @param idleTimeout
-     */
-    public void setIdleTimeout(short idleTimeout) {
-        this.idleTimeout = idleTimeout;
-    }
-
-    /**
-     * Gets a copy of the OFMatch object for this FlowMod, changes to this
-     * object do not modify the FlowMod
-     * @return
-     */
-    public OFMatch getMatch() {
-        return this.match;
-    }
-
-    /**
-     * Set match
-     * @param match
-     */
-    public void setMatch(OFMatch match) {
-        this.match = match;
-    }
-
-    /**
-     * Get priority
-     * @return
-     */
-    public short getPriority() {
-        return this.priority;
-    }
-
-    /**
-     * Set priority
-     * @param priority
-     */
-    public void setPriority(short priority) {
-        this.priority = priority;
-    }
-
-    /**
-     * @return the reason
-     */
-    public OFFlowRemovedReason getReason() {
-        return reason;
-    }
-
-    /**
-     * @param reason the reason to set
-     */
-    public void setReason(OFFlowRemovedReason reason) {
-        this.reason = reason;
-    }
-
-    /**
-     * @return the durationSeconds
-     */
-    public int getDurationSeconds() {
-        return durationSeconds;
-    }
-
-    /**
-     * @param durationSeconds the durationSeconds to set
-     */
-    public void setDurationSeconds(int durationSeconds) {
-        this.durationSeconds = durationSeconds;
-    }
-
-    /**
-     * @return the durationNanoseconds
-     */
-    public int getDurationNanoseconds() {
-        return durationNanoseconds;
-    }
-
-    /**
-     * @param durationNanoseconds the durationNanoseconds to set
-     */
-    public void setDurationNanoseconds(int durationNanoseconds) {
-        this.durationNanoseconds = durationNanoseconds;
-    }
-
-    /**
-     * @return the packetCount
-     */
-    public long getPacketCount() {
-        return packetCount;
-    }
-
-    /**
-     * @param packetCount the packetCount to set
-     */
-    public void setPacketCount(long packetCount) {
-        this.packetCount = packetCount;
-    }
-
-    /**
-     * @return the byteCount
-     */
-    public long getByteCount() {
-        return byteCount;
-    }
-
-    /**
-     * @param byteCount the byteCount to set
-     */
-    public void setByteCount(long byteCount) {
-        this.byteCount = byteCount;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        if (this.match == null)
-            this.match = new OFMatch();
-        this.match.readFrom(data);
-        this.cookie = data.readLong();
-        this.priority = data.readShort();
-        int reasonIndex = 0xff & data.readByte();
-        if (reasonIndex >= OFFlowRemovedReason.values().length) {
-            reasonIndex = OFFlowRemovedReason.values().length - 1;
-        }
-        this.reason = OFFlowRemovedReason.values()[reasonIndex];
-        data.readByte(); // pad
-        this.durationSeconds = data.readInt();
-        this.durationNanoseconds = data.readInt();
-        this.idleTimeout = data.readShort();
-        data.readByte(); // pad
-        data.readByte(); // pad
-        this.packetCount = data.readLong();
-        this.byteCount = data.readLong();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        this.match.writeTo(data);
-        data.writeLong(cookie);
-        data.writeShort(priority);
-        data.writeByte((byte) this.reason.ordinal());
-        data.writeByte((byte) 0);
-        data.writeInt(this.durationSeconds);
-        data.writeInt(this.durationNanoseconds);
-        data.writeShort(idleTimeout);
-        data.writeByte((byte) 0); // pad
-        data.writeByte((byte) 0); // pad
-        data.writeLong(this.packetCount);
-        data.writeLong(this.byteCount);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 271;
-        int result = super.hashCode();
-        result = prime * result + (int) (byteCount ^ (byteCount >>> 32));
-        result = prime * result + (int) (cookie ^ (cookie >>> 32));
-        result = prime * result + durationNanoseconds;
-        result = prime * result + durationSeconds;
-        result = prime * result + idleTimeout;
-        result = prime * result + ((match == null) ? 0 : match.hashCode());
-        result = prime * result + (int) (packetCount ^ (packetCount >>> 32));
-        result = prime * result + priority;
-        result = prime * result + ((reason == null) ? 0 : reason.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFFlowRemoved)) {
-            return false;
-        }
-        OFFlowRemoved other = (OFFlowRemoved) obj;
-        if (byteCount != other.byteCount) {
-            return false;
-        }
-        if (cookie != other.cookie) {
-            return false;
-        }
-        if (durationNanoseconds != other.durationNanoseconds) {
-            return false;
-        }
-        if (durationSeconds != other.durationSeconds) {
-            return false;
-        }
-        if (idleTimeout != other.idleTimeout) {
-            return false;
-        }
-        if (match == null) {
-            if (other.match != null) {
-                return false;
-            }
-        } else if (!match.equals(other.match)) {
-            return false;
-        }
-        if (packetCount != other.packetCount) {
-            return false;
-        }
-        if (priority != other.priority) {
-            return false;
-        }
-        if (reason == null) {
-            if (other.reason != null) {
-                return false;
-            }
-        } else if (!reason.equals(other.reason)) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFGetConfigReply.java b/src/main/java/org/openflow/protocol/OFGetConfigReply.java
deleted file mode 100644
index 257867afa..000000000
--- a/src/main/java/org/openflow/protocol/OFGetConfigReply.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-/**
- * Represents an OFPT_GET_CONFIG_REPLY type message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFGetConfigReply extends OFSwitchConfig {
-    public OFGetConfigReply() {
-        super();
-        this.type = OFType.GET_CONFIG_REPLY;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFGetConfigRequest.java b/src/main/java/org/openflow/protocol/OFGetConfigRequest.java
deleted file mode 100644
index 85c749924..000000000
--- a/src/main/java/org/openflow/protocol/OFGetConfigRequest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.util.U16;
-
-/**
- * Represents an OFPT_GET_CONFIG_REQUEST type message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFGetConfigRequest extends OFMessage {
-    public OFGetConfigRequest() {
-        super();
-        this.type = OFType.GET_CONFIG_REQUEST;
-        this.length = U16.t(OFMessage.MINIMUM_LENGTH);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFHello.java b/src/main/java/org/openflow/protocol/OFHello.java
deleted file mode 100644
index e702ca4d9..000000000
--- a/src/main/java/org/openflow/protocol/OFHello.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.util.U16;
-
-
-/**
- * Represents an ofp_hello message
- *
- * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 8, 2010
- */
-public class OFHello extends OFMessage {
-    public static int MINIMUM_LENGTH = 8;
-
-    /**
-     * Construct a ofp_hello message
-     */
-    public OFHello() {
-        super();
-        this.type = OFType.HELLO;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFMatch.java b/src/main/java/org/openflow/protocol/OFMatch.java
deleted file mode 100644
index 8c3c9f495..000000000
--- a/src/main/java/org/openflow/protocol/OFMatch.java
+++ /dev/null
@@ -1,1145 +0,0 @@
-/**
- *    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
- *    University
- *
- *    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 org.openflow.protocol;
-
-import java.io.Serializable;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-
-import net.floodlightcontroller.packet.Ethernet;
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.serializers.OFMatchJSONSerializer;
-import org.openflow.util.HexString;
-import org.openflow.util.U16;
-import org.openflow.util.U8;
-
-/**
- * Represents an ofp_match structure
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- */
-@JsonSerialize(using = OFMatchJSONSerializer.class)
-public class OFMatch implements Cloneable, Serializable {
-
-    /**
-     *
-     */
-    private static final long serialVersionUID = 1L;
-    public static int MINIMUM_LENGTH = 40;
-    final public static int OFPFW_ALL = ((1 << 22) - 1);
-
-    final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */
-    final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */
-    final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */
-    final public static int OFPFW_DL_DST = 1 << 3; /*
-                                                    * Ethernet destination
-                                                    * address.
-                                                    */
-    final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */
-    final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */
-    final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */
-    final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */
-
-    /*
-     * IP source address wildcard bit count. 0 is exact match, 1 ignores the
-     * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
-     * the entire field. This is the *opposite* of the usual convention where
-     * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded.
-     */
-    final public static int OFPFW_NW_SRC_SHIFT = 8;
-    final public static int OFPFW_NW_SRC_BITS = 6;
-    final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT;
-    final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT;
-
-    /* IP destination address wildcard bit count. Same format as source. */
-    final public static int OFPFW_NW_DST_SHIFT = 14;
-    final public static int OFPFW_NW_DST_BITS = 6;
-    final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT;
-    final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT;
-
-    final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */
-    final public static int OFPFW_NW_TOS = 1 << 21; /*
-                                                     * IP ToS (DSCP field, 6
-                                                     * bits).
-                                                     */
-
-    final public static int OFPFW_ALL_SANITIZED = (((1 << 22) - 1)
-                                                   & ~OFPFW_NW_SRC_MASK & ~OFPFW_NW_DST_MASK)
-                                                  | OFPFW_NW_SRC_ALL
-                                                  | OFPFW_NW_DST_ALL;
-
-    /* List of Strings for marshalling and unmarshalling to human readable forms */
-    final public static String STR_IN_PORT = "in_port";
-    final public static String STR_DL_DST = "dl_dst";
-    final public static String STR_DL_SRC = "dl_src";
-    final public static String STR_DL_TYPE = "dl_type";
-    final public static String STR_DL_VLAN = "dl_vlan";
-    final public static String STR_DL_VLAN_PCP = "dl_vlan_pcp";
-    final public static String STR_NW_DST = "nw_dst";
-    final public static String STR_NW_SRC = "nw_src";
-    final public static String STR_NW_PROTO = "nw_proto";
-    final public static String STR_NW_TOS = "nw_tos";
-    final public static String STR_TP_DST = "tp_dst";
-    final public static String STR_TP_SRC = "tp_src";
-
-    protected int wildcards;
-    protected short inputPort;
-    protected byte[] dataLayerSource;
-    protected byte[] dataLayerDestination;
-    protected short dataLayerVirtualLan;
-    protected byte dataLayerVirtualLanPriorityCodePoint;
-    protected short dataLayerType;
-    protected byte networkTypeOfService;
-    protected byte networkProtocol;
-    protected int networkSource;
-    protected int networkDestination;
-    protected short transportSource;
-    protected short transportDestination;
-
-    /**
-     * By default, create a OFMatch that matches everything (mostly because it's
-     * the least amount of work to make a valid OFMatch)
-     */
-    public OFMatch() {
-        this.wildcards = OFPFW_ALL;
-        this.dataLayerDestination = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0,
-                                                0x0 };
-        this.dataLayerSource = new byte[] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
-        this.dataLayerVirtualLan = Ethernet.VLAN_UNTAGGED;
-        this.dataLayerVirtualLanPriorityCodePoint = 0;
-        this.dataLayerType = 0;
-        this.inputPort = 0;
-        this.networkProtocol = 0;
-        this.networkTypeOfService = 0;
-        this.networkSource = 0;
-        this.networkDestination = 0;
-        this.transportDestination = 0;
-        this.transportSource = 0;
-    }
-
-    /**
-     * Get dl_dst
-     *
-     * @return an arrays of bytes
-     */
-    public byte[] getDataLayerDestination() {
-        return this.dataLayerDestination;
-    }
-
-    /**
-     * Set dl_dst
-     *
-     * @param dataLayerDestination
-     */
-    public OFMatch setDataLayerDestination(byte[] dataLayerDestination) {
-        this.dataLayerDestination = dataLayerDestination;
-        return this;
-    }
-
-    /**
-     * Set dl_dst, but first translate to byte[] using HexString
-     *
-     * @param mac
-     *            A colon separated string of 6 pairs of octets, e..g.,
-     *            "00:17:42:EF:CD:8D"
-     */
-    public OFMatch setDataLayerDestination(String mac) {
-        byte bytes[] = HexString.fromHexString(mac);
-        if (bytes.length != 6)
-                              throw new IllegalArgumentException(
-                                                                 "expected string with 6 octets, got '"
-                                                                         + mac
-                                                                         + "'");
-        this.dataLayerDestination = bytes;
-        return this;
-    }
-
-    /**
-     * Get dl_src
-     *
-     * @return an array of bytes
-     */
-    public byte[] getDataLayerSource() {
-        return this.dataLayerSource;
-    }
-
-    /**
-     * Set dl_src
-     *
-     * @param dataLayerSource
-     */
-    public OFMatch setDataLayerSource(byte[] dataLayerSource) {
-        this.dataLayerSource = dataLayerSource;
-        return this;
-    }
-
-    /**
-     * Set dl_src, but first translate to byte[] using HexString
-     *
-     * @param mac
-     *            A colon separated string of 6 pairs of octets, e..g.,
-     *            "00:17:42:EF:CD:8D"
-     */
-    public OFMatch setDataLayerSource(String mac) {
-        byte bytes[] = HexString.fromHexString(mac);
-        if (bytes.length != 6)
-                              throw new IllegalArgumentException(
-                                                                 "expected string with 6 octets, got '"
-                                                                         + mac
-                                                                         + "'");
-        this.dataLayerSource = bytes;
-        return this;
-    }
-
-    /**
-     * Get dl_type
-     *
-     * @return ether_type
-     */
-    public short getDataLayerType() {
-        return this.dataLayerType;
-    }
-
-    /**
-     * Set dl_type
-     *
-     * @param dataLayerType
-     */
-    public OFMatch setDataLayerType(short dataLayerType) {
-        this.dataLayerType = dataLayerType;
-        return this;
-    }
-
-    /**
-     * Get dl_vlan
-     *
-     * @return vlan tag; VLAN_NONE == no tag
-     */
-    public short getDataLayerVirtualLan() {
-        return this.dataLayerVirtualLan;
-    }
-
-    /**
-     * Set dl_vlan
-     *
-     * @param dataLayerVirtualLan
-     */
-    public OFMatch setDataLayerVirtualLan(short dataLayerVirtualLan) {
-        this.dataLayerVirtualLan = dataLayerVirtualLan;
-        return this;
-    }
-
-    /**
-     * Get dl_vlan_pcp
-     *
-     * @return
-     */
-    public byte getDataLayerVirtualLanPriorityCodePoint() {
-        return this.dataLayerVirtualLanPriorityCodePoint;
-    }
-
-    /**
-     * Set dl_vlan_pcp
-     *
-     * @param pcp
-     */
-    public OFMatch setDataLayerVirtualLanPriorityCodePoint(byte pcp) {
-        this.dataLayerVirtualLanPriorityCodePoint = pcp;
-        return this;
-    }
-
-    /**
-     * Get in_port
-     *
-     * @return
-     */
-    public short getInputPort() {
-        return this.inputPort;
-    }
-
-    /**
-     * Set in_port
-     *
-     * @param inputPort
-     */
-    public OFMatch setInputPort(short inputPort) {
-        this.inputPort = inputPort;
-        return this;
-    }
-
-    /**
-     * Get nw_dst
-     *
-     * @return
-     */
-    public int getNetworkDestination() {
-        return this.networkDestination;
-    }
-
-    /**
-     * Set nw_dst
-     *
-     * @param networkDestination
-     */
-    public OFMatch setNetworkDestination(int networkDestination) {
-        this.networkDestination = networkDestination;
-        return this;
-    }
-
-    /**
-     * Parse this match's wildcard fields and return the number of significant
-     * bits in the IP destination field. NOTE: this returns the number of bits
-     * that are fixed, i.e., like CIDR, not the number of bits that are free
-     * like OpenFlow encodes.
-     *
-     * @return a number between 0 (matches all IPs) and 63 ( 32>= implies exact
-     *         match)
-     */
-    public int getNetworkDestinationMaskLen() {
-        return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
-                        0);
-    }
-
-    /**
-     * Parse this match's wildcard fields and return the number of significant
-     * bits in the IP destination field. NOTE: this returns the number of bits
-     * that are fixed, i.e., like CIDR, not the number of bits that are free
-     * like OpenFlow encodes.
-     *
-     * @return a number between 0 (matches all IPs) and 32 (exact match)
-     */
-    public int getNetworkSourceMaskLen() {
-        return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
-                        0);
-    }
-
-    /**
-     * Get nw_proto
-     *
-     * @return
-     */
-    public byte getNetworkProtocol() {
-        return this.networkProtocol;
-    }
-
-    /**
-     * Set nw_proto
-     *
-     * @param networkProtocol
-     */
-    public OFMatch setNetworkProtocol(byte networkProtocol) {
-        this.networkProtocol = networkProtocol;
-        return this;
-    }
-
-    /**
-     * Get nw_src
-     *
-     * @return
-     */
-    public int getNetworkSource() {
-        return this.networkSource;
-    }
-
-    /**
-     * Set nw_src
-     *
-     * @param networkSource
-     */
-    public OFMatch setNetworkSource(int networkSource) {
-        this.networkSource = networkSource;
-        return this;
-    }
-
-    /**
-     * Get nw_tos OFMatch stores the ToS bits as top 6-bits, so right shift by 2
-     * bits before returning the value
-     *
-     * @return : 6-bit DSCP value (0-63)
-     */
-    public byte getNetworkTypeOfService() {
-        return (byte) ((this.networkTypeOfService >> 2) & 0x3f);
-    }
-
-    /**
-     * Set nw_tos OFMatch stores the ToS bits as top 6-bits, so left shift by 2
-     * bits before storing the value
-     *
-     * @param networkTypeOfService
-     *            : 6-bit DSCP value (0-63)
-     */
-    public OFMatch setNetworkTypeOfService(byte networkTypeOfService) {
-        this.networkTypeOfService = (byte) (networkTypeOfService << 2);
-        return this;
-    }
-
-    /**
-     * Get tp_dst
-     *
-     * @return
-     */
-    public short getTransportDestination() {
-        return this.transportDestination;
-    }
-
-    /**
-     * Set tp_dst
-     *
-     * @param transportDestination
-     */
-    public OFMatch setTransportDestination(short transportDestination) {
-        this.transportDestination = transportDestination;
-        return this;
-    }
-
-    /**
-     * Get tp_src
-     *
-     * @return
-     */
-    public short getTransportSource() {
-        return this.transportSource;
-    }
-
-    /**
-     * Set tp_src
-     *
-     * @param transportSource
-     */
-    public OFMatch setTransportSource(short transportSource) {
-        this.transportSource = transportSource;
-        return this;
-    }
-
-    /**
-     * Get wildcards
-     *
-     * @return
-     */
-    public int getWildcards() {
-        return this.wildcards;
-    }
-
-    /**
-     * Get wildcards
-     *
-     * @return
-     */
-    public Wildcards getWildcardObj() {
-        return Wildcards.of(wildcards);
-    }
-
-    /**
-     * Set wildcards
-     *
-     * @param wildcards
-     */
-    public OFMatch setWildcards(int wildcards) {
-        this.wildcards = wildcards;
-        return this;
-    }
-
-    /** set the wildcard using the Wildcards convenience object */
-    public OFMatch setWildcards(Wildcards wildcards) {
-        this.wildcards = wildcards.getInt();
-        return this;
-    }
-
-    /**
-     * Initializes this OFMatch structure with the corresponding data from the
-     * specified packet. Must specify the input port, to ensure that
-     * this.in_port is set correctly. Specify OFPort.NONE or OFPort.ANY if input
-     * port not applicable or available
-     *
-     * @param packetData
-     *            The packet's data
-     * @param inputPort
-     *            the port the packet arrived on
-     */
-    public OFMatch loadFromPacket(byte[] packetData, short inputPort) {
-        short scratch;
-        int transportOffset = 34;
-        ByteBuffer packetDataBB = ByteBuffer.wrap(packetData);
-        int limit = packetDataBB.limit();
-
-        this.wildcards = 0; // all fields have explicit entries
-
-        this.inputPort = inputPort;
-
-        if (inputPort == OFPort.OFPP_ALL.getValue())
-                                                    this.wildcards |= OFPFW_IN_PORT;
-
-        assert (limit >= 14);
-        // dl dst
-        this.dataLayerDestination = new byte[6];
-        packetDataBB.get(this.dataLayerDestination);
-        // dl src
-        this.dataLayerSource = new byte[6];
-        packetDataBB.get(this.dataLayerSource);
-        // dl type
-        this.dataLayerType = packetDataBB.getShort();
-
-        if (getDataLayerType() != (short) 0x8100) { // need cast to avoid signed
-            // bug
-            setDataLayerVirtualLan((short) 0xffff);
-            setDataLayerVirtualLanPriorityCodePoint((byte) 0);
-        } else {
-            // has vlan tag
-            scratch = packetDataBB.getShort();
-            setDataLayerVirtualLan((short) (0xfff & scratch));
-            setDataLayerVirtualLanPriorityCodePoint((byte) ((0xe000 & scratch) >> 13));
-            this.dataLayerType = packetDataBB.getShort();
-        }
-
-        switch (getDataLayerType()) {
-            case 0x0800:
-                // ipv4
-                // check packet length
-                scratch = packetDataBB.get();
-                scratch = (short) (0xf & scratch);
-                transportOffset = (packetDataBB.position() - 1)
-                                  + (scratch * 4);
-                // nw tos (dscp)
-                scratch = packetDataBB.get();
-                setNetworkTypeOfService((byte) ((0xfc & scratch) >> 2));
-                // nw protocol
-                packetDataBB.position(packetDataBB.position() + 7);
-                this.networkProtocol = packetDataBB.get();
-                // nw src
-                packetDataBB.position(packetDataBB.position() + 2);
-                this.networkSource = packetDataBB.getInt();
-                // nw dst
-                this.networkDestination = packetDataBB.getInt();
-                packetDataBB.position(transportOffset);
-                break;
-            case 0x0806:
-                // arp
-                int arpPos = packetDataBB.position();
-                // opcode
-                scratch = packetDataBB.getShort(arpPos + 6);
-                setNetworkProtocol((byte) (0xff & scratch));
-
-                scratch = packetDataBB.getShort(arpPos + 2);
-                // if ipv4 and addr len is 4
-                if (scratch == 0x800 && packetDataBB.get(arpPos + 5) == 4) {
-                    // nw src
-                    this.networkSource = packetDataBB.getInt(arpPos + 14);
-                    // nw dst
-                    this.networkDestination = packetDataBB.getInt(arpPos + 24);
-                } else {
-                    setNetworkSource(0);
-                    setNetworkDestination(0);
-                }
-                break;
-            default:
-                // Not ARP or IP. Wildcard NW_DST and NW_SRC
-                this.wildcards |= OFPFW_NW_DST_ALL |
-                                  OFPFW_NW_SRC_ALL |
-                                  OFPFW_NW_PROTO |
-                                  OFPFW_NW_TOS;
-                setNetworkTypeOfService((byte) 0);
-                setNetworkProtocol((byte) 0);
-                setNetworkSource(0);
-                setNetworkDestination(0);
-                break;
-        }
-
-        switch (getNetworkProtocol()) {
-            case 0x01:
-                // icmp
-                // type
-                this.transportSource = U8.f(packetDataBB.get());
-                // code
-                this.transportDestination = U8.f(packetDataBB.get());
-                break;
-            case 0x06:
-                // tcp
-                // tcp src
-                this.transportSource = packetDataBB.getShort();
-                // tcp dest
-                this.transportDestination = packetDataBB.getShort();
-                break;
-            case 0x11:
-                // udp
-                // udp src
-                this.transportSource = packetDataBB.getShort();
-                // udp dest
-                this.transportDestination = packetDataBB.getShort();
-                break;
-            default:
-                // Unknown network proto.
-                this.wildcards |= OFPFW_TP_DST | OFPFW_TP_SRC;
-                setTransportDestination((short) 0);
-                setTransportSource((short) 0);
-                break;
-        }
-        return this;
-    }
-
-    /**
-     * Read this message off the wire from the specified ByteBuffer
-     *
-     * @param data
-     */
-    public void readFrom(ChannelBuffer data) {
-        this.wildcards = data.readInt();
-        this.inputPort = data.readShort();
-        this.dataLayerSource = new byte[6];
-        data.readBytes(this.dataLayerSource);
-        this.dataLayerDestination = new byte[6];
-        data.readBytes(this.dataLayerDestination);
-        this.dataLayerVirtualLan = data.readShort();
-        this.dataLayerVirtualLanPriorityCodePoint = data.readByte();
-        data.readByte(); // pad
-        this.dataLayerType = data.readShort();
-        this.networkTypeOfService = data.readByte();
-        this.networkProtocol = data.readByte();
-        data.readByte(); // pad
-        data.readByte(); // pad
-        this.networkSource = data.readInt();
-        this.networkDestination = data.readInt();
-        this.transportSource = data.readShort();
-        this.transportDestination = data.readShort();
-    }
-
-    /**
-     * Write this message's binary format to the specified ByteBuffer
-     *
-     * @param data
-     */
-    public void writeTo(ChannelBuffer data) {
-        data.writeInt(wildcards);
-        data.writeShort(inputPort);
-        data.writeBytes(this.dataLayerSource);
-        data.writeBytes(this.dataLayerDestination);
-        data.writeShort(dataLayerVirtualLan);
-        data.writeByte(dataLayerVirtualLanPriorityCodePoint);
-        data.writeByte((byte) 0x0); // pad
-        data.writeShort(dataLayerType);
-        data.writeByte(networkTypeOfService);
-        data.writeByte(networkProtocol);
-        data.writeByte((byte) 0x0); // pad
-        data.writeByte((byte) 0x0); // pad
-        data.writeInt(networkSource);
-        data.writeInt(networkDestination);
-        data.writeShort(transportSource);
-        data.writeShort(transportDestination);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 131;
-        int result = 1;
-        result = prime * result + Arrays.hashCode(dataLayerDestination);
-        result = prime * result + Arrays.hashCode(dataLayerSource);
-        result = prime * result + dataLayerType;
-        result = prime * result + dataLayerVirtualLan;
-        result = prime * result + dataLayerVirtualLanPriorityCodePoint;
-        result = prime * result + inputPort;
-        result = prime * result + networkDestination;
-        result = prime * result + networkProtocol;
-        result = prime * result + networkSource;
-        result = prime * result + networkTypeOfService;
-        result = prime * result + transportDestination;
-        result = prime * result + transportSource;
-        result = prime * result + wildcards;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFMatch)) {
-            return false;
-        }
-        OFMatch other = (OFMatch) obj;
-        if (!Arrays.equals(dataLayerDestination, other.dataLayerDestination)) {
-            return false;
-        }
-        if (!Arrays.equals(dataLayerSource, other.dataLayerSource)) {
-            return false;
-        }
-        if (dataLayerType != other.dataLayerType) {
-            return false;
-        }
-        if (dataLayerVirtualLan != other.dataLayerVirtualLan) {
-            return false;
-        }
-        if (dataLayerVirtualLanPriorityCodePoint != other.dataLayerVirtualLanPriorityCodePoint) {
-            return false;
-        }
-        if (inputPort != other.inputPort) {
-            return false;
-        }
-        if (networkDestination != other.networkDestination) {
-            return false;
-        }
-        if (networkProtocol != other.networkProtocol) {
-            return false;
-        }
-        if (networkSource != other.networkSource) {
-            return false;
-        }
-        if (networkTypeOfService != other.networkTypeOfService) {
-            return false;
-        }
-        if (transportDestination != other.transportDestination) {
-            return false;
-        }
-        if (transportSource != other.transportSource) {
-            return false;
-        }
-        if ((wildcards & OFMatch.OFPFW_ALL) != (other.wildcards & OFPFW_ALL)) { // only
-            // consider
-            // allocated
-            // part
-            // of
-            // wildcards
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Implement clonable interface
-     */
-    @Override
-    public OFMatch clone() {
-        try {
-            OFMatch ret = (OFMatch) super.clone();
-            ret.dataLayerDestination = this.dataLayerDestination.clone();
-            ret.dataLayerSource = this.dataLayerSource.clone();
-            return ret;
-        } catch (CloneNotSupportedException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * matching two OFMatch
-     * @param toCompare
-     * @return
-     */
-    public boolean match(OFMatch toCompare) {
-        if ((wildcards & OFPFW_IN_PORT) == 0 &&
-                this.inputPort != toCompare.getInputPort())
-            return false;
-        if ((wildcards & OFPFW_DL_DST) == 0 &&
-                !Arrays.equals(this.dataLayerDestination, toCompare.getDataLayerDestination()))
-            return false;
-        if ((wildcards & OFPFW_DL_SRC) == 0 &&
-                !Arrays.equals(this.dataLayerSource, toCompare.getDataLayerSource()))
-            return false;
-        if ((wildcards & OFPFW_DL_TYPE) == 0
-                && this.dataLayerType != toCompare.getDataLayerType())
-            return false;
-        if ((wildcards & OFPFW_DL_VLAN) == 0 &&
-                this.dataLayerVirtualLan != toCompare.getDataLayerVirtualLan())
-            return false;
-        if ((wildcards & OFPFW_DL_VLAN_PCP) == 0 &&
-                this.dataLayerVirtualLanPriorityCodePoint != toCompare.getDataLayerVirtualLanPriorityCodePoint())
-            return false;
-        if ((wildcards & OFPFW_NW_PROTO) == 0 &&
-                this.networkProtocol != toCompare.getNetworkProtocol())
-            return false;
-        if ((wildcards & OFPFW_NW_TOS) == 0 &&
-                this.networkTypeOfService != toCompare.getNetworkTypeOfService())
-            return false;
-        //compare network layer src/dst
-
-        int dstmasklen = getNetworkDestinationMaskLen();
-        int srcmasklen = getNetworkSourceMaskLen();
-        if (dstmasklen >= 32 && networkDestination != toCompare.getNetworkDestination())
-            return false;
-        if (srcmasklen >= 32 && networkSource != toCompare.getNetworkSource())
-            return false;
-        int dstmask = ~((1 << (32 - dstmasklen)) - 1);
-        int srcmask = ~((1 << (32 - srcmasklen)) - 1);
-        if (dstmasklen < 32 &&
-                (networkDestination & dstmask) != (toCompare.getNetworkDestination() & dstmask))
-            return false;
-        if (srcmasklen < 32 &&
-                (networkSource & srcmask) != (toCompare.getNetworkSource() & srcmask))
-            return false;
-        //layer 4
-        if ((wildcards & OFPFW_TP_DST) == 0 &&
-                this.transportDestination != toCompare.getTransportDestination())
-            return false;
-        if ((wildcards & OFPFW_TP_SRC) == 0 &&
-                this.transportSource != toCompare.getTransportSource())
-            return false;
-        return true;
-    }
-
-    /**
-     * Output a dpctl-styled string, i.e., only list the elements that are not
-     * wildcarded A match-everything OFMatch outputs "OFMatch[]"
-     *
-     * @return
-     *         "OFMatch[dl_src:00:20:01:11:22:33,nw_src:192.168.0.0/24,tp_dst:80]"
-     */
-    @Override
-    public String toString() {
-        String str = "";
-
-        // l1
-        if ((wildcards & OFPFW_IN_PORT) == 0)
-                                             str += "," + STR_IN_PORT + "="
-                                                    + U16.f(this.inputPort);
-
-        // l2
-        if ((wildcards & OFPFW_DL_DST) == 0)
-                                            str += ","
-                                                   + STR_DL_DST
-                                                   + "="
-                                                   + HexString.toHexString(this.dataLayerDestination);
-        if ((wildcards & OFPFW_DL_SRC) == 0)
-                                            str += ","
-                                                   + STR_DL_SRC
-                                                   + "="
-                                                   + HexString.toHexString(this.dataLayerSource);
-        if ((wildcards & OFPFW_DL_TYPE) == 0)
-                                             str += ","
-                                                    + STR_DL_TYPE
-                                                    + "=0x"
-                                                    + Integer.toHexString(U16.f(this.dataLayerType));
-        if ((wildcards & OFPFW_DL_VLAN) == 0)
-                                             str += ","
-                                                    + STR_DL_VLAN
-                                                    + "=0x"
-                                                    + Integer.toHexString(U16.f(this.dataLayerVirtualLan));
-        if ((wildcards & OFPFW_DL_VLAN_PCP) == 0)
-                                                 str += ","
-                                                        + STR_DL_VLAN_PCP
-                                                        + "="
-                                                        + Integer.toHexString(U8.f(this.dataLayerVirtualLanPriorityCodePoint));
-
-        // l3
-        if (getNetworkDestinationMaskLen() > 0)
-                                               str += ","
-                                                      + STR_NW_DST
-                                                      + "="
-                                                      + cidrToString(networkDestination,
-                                                                     getNetworkDestinationMaskLen());
-        if (getNetworkSourceMaskLen() > 0)
-                                          str += ","
-                                                 + STR_NW_SRC
-                                                 + "="
-                                                 + cidrToString(networkSource,
-                                                                getNetworkSourceMaskLen());
-        if ((wildcards & OFPFW_NW_PROTO) == 0)
-                                              str += "," + STR_NW_PROTO
-                                                     + "="
-                                                     + this.networkProtocol;
-        if ((wildcards & OFPFW_NW_TOS) == 0)
-                                            str += ","
-                                                   + STR_NW_TOS
-                                                   + "="
-                                                   + this.getNetworkTypeOfService();
-
-        // l4
-        if ((wildcards & OFPFW_TP_DST) == 0)
-                                            str += ","
-                                                   + STR_TP_DST
-                                                   + "="
-                                                   + this.transportDestination;
-        if ((wildcards & OFPFW_TP_SRC) == 0)
-                                            str += "," + STR_TP_SRC + "="
-                                                   + this.transportSource;
-        if ((str.length() > 0) && (str.charAt(0) == ','))
-                                                         str = str.substring(1); // trim
-                                                                                 // the
-                                                                                 // leading
-                                                                                 // ","
-        // done
-        return "OFMatch[" + str + "]";
-    }
-
-    /**
-     * Return a string including all match fields, regardless whether they
-     * are wildcarded or not.
-     */
-    public String toStringUnmasked() {
-        String str = "";
-
-        // l1
-        str += STR_IN_PORT + "=" + U16.f(this.inputPort);
-
-        // l2
-        str += "," + STR_DL_DST + "="
-                + HexString.toHexString(this.dataLayerDestination);
-        str += "," + STR_DL_SRC + "="
-                + HexString.toHexString(this.dataLayerSource);
-        str += "," + STR_DL_TYPE + "=0x"
-                + Integer.toHexString(U16.f(this.dataLayerType));
-        str += "," + STR_DL_VLAN + "=0x"
-                + Integer.toHexString(U16.f(this.dataLayerVirtualLan));
-        str += "," + STR_DL_VLAN_PCP + "="
-                + Integer.toHexString(U8.f(this.dataLayerVirtualLanPriorityCodePoint));
-
-        // l3
-        str += "," + STR_NW_DST + "="
-                + cidrToString(networkDestination,
-                               getNetworkDestinationMaskLen());
-        str += "," + STR_NW_SRC + "="
-                + cidrToString(networkSource,
-                               getNetworkSourceMaskLen());
-        str += "," + STR_NW_PROTO + "=" + this.networkProtocol;
-        str += "," + STR_NW_TOS + "=" + this.getNetworkTypeOfService();
-
-        // l4
-        str += "," + STR_TP_DST + "=" + this.transportDestination;
-        str += "," + STR_TP_SRC + "=" + this.transportSource;
-
-        // wildcards
-        str += ", wildcards=" + debugWildCards(wildcards);
-        return "OFMatch[" + str + "]";
-    }
-
-    /**
-     * debug a set of wildcards
-     */
-    public static String debugWildCards(int wildcards) {
-        String str = "";
-
-        // l1
-        if ((wildcards & OFPFW_IN_PORT) != 0) str += "|" + STR_IN_PORT;
-
-        // l2
-        if ((wildcards & OFPFW_DL_DST) != 0) str += "|" + STR_DL_DST;
-        if ((wildcards & OFPFW_DL_SRC) != 0) str += "|" + STR_DL_SRC;
-        if ((wildcards & OFPFW_DL_TYPE) != 0) str += "|" + STR_DL_TYPE;
-        if ((wildcards & OFPFW_DL_VLAN) != 0) str += "|" + STR_DL_VLAN;
-        if ((wildcards & OFPFW_DL_VLAN_PCP) != 0)
-                                                 str += "|"
-                                                        + STR_DL_VLAN_PCP;
-
-        int nwDstMask = Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
-                                 0);
-        int nwSrcMask = Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
-                                 0);
-
-        // l3
-        if (nwDstMask < 32)
-                           str += "|" + STR_NW_DST + "(/" + nwDstMask + ")";
-
-        if (nwSrcMask < 32)
-                           str += "|" + STR_NW_SRC + "(/" + nwSrcMask + ")";
-
-        if ((wildcards & OFPFW_NW_PROTO) != 0) str += "|" + STR_NW_PROTO;
-        if ((wildcards & OFPFW_NW_TOS) != 0) str += "|" + STR_NW_TOS;
-
-        // l4
-        if ((wildcards & OFPFW_TP_DST) != 0) str += "|" + STR_TP_DST;
-        if ((wildcards & OFPFW_TP_SRC) != 0) str += "|" + STR_TP_SRC;
-        if ((str.length() > 0) && (str.charAt(0) == '|'))
-                                                         str = str.substring(1); // trim
-                                                                                 // the
-                                                                                 // leading
-                                                                                 // ","
-        // done
-        return str;
-    }
-
-    private String cidrToString(int ip, int prefix) {
-        String str;
-        if (prefix >= 32) {
-            str = ipToString(ip);
-        } else {
-            // use the negation of mask to fake endian magic
-            int mask = ~((1 << (32 - prefix)) - 1);
-            str = ipToString(ip & mask) + "/" + prefix;
-        }
-
-        return str;
-    }
-
-    /**
-     * Set this OFMatch's parameters based on a comma-separated key=value pair
-     * dpctl-style string, e.g., from the output of OFMatch.toString() <br>
-     * <p>
-     * Supported keys/values include <br>
-     * <p>
-     * <TABLE border=1>
-     * <TR>
-     * <TD>KEY(s)
-     * <TD>VALUE
-     * </TR>
-     * <TR>
-     * <TD>"in_port","input_port"
-     * <TD>integer
-     * </TR>
-     * <TR>
-     * <TD>"dl_src","eth_src", "dl_dst","eth_dst"
-     * <TD>hex-string
-     * </TR>
-     * <TR>
-     * <TD>"dl_type", "dl_vlan", "dl_vlan_pcp"
-     * <TD>integer
-     * </TR>
-     * <TR>
-     * <TD>"nw_src", "nw_dst", "ip_src", "ip_dst"
-     * <TD>CIDR-style netmask
-     * </TR>
-     * <TR>
-     * <TD>"tp_src","tp_dst"
-     * <TD>integer (max 64k)
-     * </TR>
-     * </TABLE>
-     * <p>
-     * The CIDR-style netmasks assume 32 netmask if none given, so:
-     * "128.8.128.118/32" is the same as "128.8.128.118"
-     *
-     * @param match
-     *            a key=value comma separated string, e.g.
-     *            "in_port=5,ip_dst=192.168.0.0/16,tp_src=80"
-     * @throws IllegalArgumentException
-     *             on unexpected key or value
-     */
-
-    public void fromString(String match) throws IllegalArgumentException {
-        if (match.equals("") || match.equalsIgnoreCase("any")
-            || match.equalsIgnoreCase("all") || match.equals("[]"))
-                                                                   match = "OFMatch[]";
-        String[] tokens = match.split("[\\[,\\]]");
-        String[] values;
-        int initArg = 0;
-        if (tokens[0].equals("OFMatch")) initArg = 1;
-        this.wildcards = OFPFW_ALL;
-        int i;
-        for (i = initArg; i < tokens.length; i++) {
-            values = tokens[i].split("=");
-            if (values.length != 2)
-                                   throw new IllegalArgumentException(
-                                                                      "Token "
-                                                                              + tokens[i]
-                                                                              + " does not have form 'key=value' parsing "
-                                                                              + match);
-            values[0] = values[0].toLowerCase(); // try to make this case insens
-            if (values[0].equals(STR_IN_PORT)
-                || values[0].equals("input_port")) {
-                this.inputPort = U16.t(Integer.valueOf(values[1]));
-                this.wildcards &= ~OFPFW_IN_PORT;
-            } else if (values[0].equals(STR_DL_DST)
-                       || values[0].equals("eth_dst")) {
-                this.dataLayerDestination = HexString.fromHexString(values[1]);
-                this.wildcards &= ~OFPFW_DL_DST;
-            } else if (values[0].equals(STR_DL_SRC)
-                       || values[0].equals("eth_src")) {
-                this.dataLayerSource = HexString.fromHexString(values[1]);
-                this.wildcards &= ~OFPFW_DL_SRC;
-            } else if (values[0].equals(STR_DL_TYPE)
-                       || values[0].equals("eth_type")) {
-                if (values[1].startsWith("0x"))
-                    this.dataLayerType = U16.t(Integer.valueOf(values[1].replaceFirst("0x",
-                                                                                      ""),
-                                                               16));
-                else
-                    this.dataLayerType = U16.t(Integer.valueOf(values[1]));
-                this.wildcards &= ~OFPFW_DL_TYPE;
-            } else if (values[0].equals(STR_DL_VLAN)) {
-                if (values[1].startsWith("0x"))
-                    this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1].replaceFirst("0x",
-                                                                                            ""),
-                                                                     16));
-                else
-                    this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1]));
-                this.wildcards &= ~OFPFW_DL_VLAN;
-            } else if (values[0].equals(STR_DL_VLAN_PCP)) {
-                this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short.valueOf(values[1]));
-                this.wildcards &= ~OFPFW_DL_VLAN_PCP;
-            } else if (values[0].equals(STR_NW_DST)
-                       || values[0].equals("ip_dst")) {
-                setFromCIDR(values[1], STR_NW_DST);
-            } else if (values[0].equals(STR_NW_SRC)
-                       || values[0].equals("ip_src")) {
-                setFromCIDR(values[1], STR_NW_SRC);
-            } else if (values[0].equals(STR_NW_PROTO)) {
-                if (values[1].startsWith("0x"))
-                    this.networkProtocol = U8.t(Short.valueOf(values[1].replaceFirst("0x",""),16));
-                else
-                    this.networkProtocol = U8.t(Short.valueOf(values[1]));
-                this.wildcards &= ~OFPFW_NW_PROTO;
-            } else if (values[0].equals(STR_NW_TOS)) {
-                this.setNetworkTypeOfService(U8.t(Short.valueOf(values[1])));
-                this.wildcards &= ~OFPFW_NW_TOS;
-            } else if (values[0].equals(STR_TP_DST)) {
-                this.transportDestination = U16.t(Integer.valueOf(values[1]));
-                this.wildcards &= ~OFPFW_TP_DST;
-            } else if (values[0].equals(STR_TP_SRC)) {
-                this.transportSource = U16.t(Integer.valueOf(values[1]));
-                this.wildcards &= ~OFPFW_TP_SRC;
-            } else {
-                throw new IllegalArgumentException("unknown token "
-                                                   + tokens[i] + " parsing "
-                                                   + match);
-            }
-        }
-    }
-
-    /**
-     * Set the networkSource or networkDestionation address and their wildcards
-     * from the CIDR string
-     *
-     * @param cidr
-     *            "192.168.0.0/16" or "172.16.1.5"
-     * @param which
-     *            one of STR_NW_DST or STR_NW_SRC
-     * @throws IllegalArgumentException
-     */
-    private
-            void
-            setFromCIDR(String cidr, String which)
-                                                  throws IllegalArgumentException {
-        String values[] = cidr.split("/");
-        String[] ip_str = values[0].split("\\.");
-        int ip = 0;
-        ip += Integer.valueOf(ip_str[0]) << 24;
-        ip += Integer.valueOf(ip_str[1]) << 16;
-        ip += Integer.valueOf(ip_str[2]) << 8;
-        ip += Integer.valueOf(ip_str[3]);
-        int prefix = 32; // all bits are fixed, by default
-
-        if (values.length >= 2) prefix = Integer.valueOf(values[1]);
-        int mask = 32 - prefix;
-        if (which.equals(STR_NW_DST)) {
-            this.networkDestination = ip;
-            this.wildcards = (wildcards & ~OFPFW_NW_DST_MASK)
-                             | (mask << OFPFW_NW_DST_SHIFT);
-        } else if (which.equals(STR_NW_SRC)) {
-            this.networkSource = ip;
-            this.wildcards = (wildcards & ~OFPFW_NW_SRC_MASK)
-                             | (mask << OFPFW_NW_SRC_SHIFT);
-        }
-    }
-
-    protected static String ipToString(int ip) {
-        return Integer.toString(U8.f((byte) ((ip & 0xff000000) >> 24)))
-               + "." + Integer.toString((ip & 0x00ff0000) >> 16) + "."
-               + Integer.toString((ip & 0x0000ff00) >> 8) + "."
-               + Integer.toString(ip & 0x000000ff);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java b/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java
deleted file mode 100644
index 97e14a559..000000000
--- a/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol;
-
-import java.beans.IntrospectionException;
-import java.beans.PropertyDescriptor;
-import java.beans.SimpleBeanInfo;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * Extra info for how to treat OFMatch as a JavaBean
- *
- * For some (inane!) reason, using chained setters in OFMatch breaks a lot of the JavaBean defaults.
- *
- * We don't really use OFMatch as a java bean, but there are a lot of nice XML utils that work for
- * free if OFMatch follows the java bean paradigm.
- *
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- *
- */
-
-public class OFMatchBeanInfo extends SimpleBeanInfo {
-
-    @Override
-    public PropertyDescriptor[] getPropertyDescriptors() {
-        List<PropertyDescriptor> descs = new LinkedList<PropertyDescriptor>();
-        Field[] fields = OFMatch.class.getDeclaredFields();
-        String name;
-        for (int i=0; i< fields.length; i++) {
-            int mod = fields[i].getModifiers();
-            if(Modifier.isFinal(mod) ||     // don't expose static or final fields
-                    Modifier.isStatic(mod))
-                continue;
-
-            name = fields[i].getName();
-            Class<?> type = fields[i].getType();
-
-            try {
-                descs.add(new PropertyDescriptor(name,
-                        name2getter(OFMatch.class, name),
-                        name2setter(OFMatch.class, name, type)));
-            } catch (IntrospectionException e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        return descs.toArray(new PropertyDescriptor[0]);
-    }
-
-
-    private Method name2setter(Class<OFMatch> c, String name, Class<?> type) {
-        String mName = "set" + toLeadingCaps(name);
-        Method m = null;
-        try {
-            m = c.getMethod(mName, new Class[]{ type});
-        } catch (SecurityException e) {
-            throw new RuntimeException(e);
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException(e);
-        }
-        return m;
-    }
-
-    private Method name2getter(Class<OFMatch> c, String name) {
-        String mName= "get" + toLeadingCaps(name);
-        Method m = null;
-        try {
-            m = c.getMethod(mName, new Class[]{});
-        } catch (SecurityException e) {
-            throw new RuntimeException(e);
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException(e);
-        }
-        return m;
-    }
-
-    private String toLeadingCaps(String s) {
-        char[] array = s.toCharArray();
-        array[0] = Character.toUpperCase(array[0]);
-        return String.valueOf(array, 0, array.length);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java b/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java
deleted file mode 100644
index 04ecf5e5e..000000000
--- a/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java
+++ /dev/null
@@ -1,92 +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 org.openflow.protocol;
-
-import org.openflow.util.HexString;
-
-public class OFMatchWithSwDpid {
-    protected OFMatch ofMatch;
-    protected long  switchDataPathId;
-
-    public OFMatchWithSwDpid() {
-    	this.ofMatch = new OFMatch();
-    	this.switchDataPathId = 0;
-    }
-    
-    public OFMatchWithSwDpid(OFMatch ofm, long swDpid) {
-    	this.ofMatch = ofm.clone();
-    	this.switchDataPathId = swDpid;
-    }
-    public OFMatch getOfMatch() {
-		return ofMatch;
-	}
-
-	public void setOfMatch(OFMatch ofMatch) {
-		this.ofMatch = ofMatch.clone();
-	}
-
-	public long getSwitchDataPathId() {
-        return this.switchDataPathId;
-    }
-
-    public OFMatchWithSwDpid setSwitchDataPathId(long dpid) {
-        this.switchDataPathId = dpid;
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        return "OFMatchWithSwDpid [" + HexString.toHexString(switchDataPathId)
-                + " " + ofMatch + "]";
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result
-                 + ((ofMatch == null) ? 0 : ofMatch.hashCode());
-        result = prime * result
-                 + (int) (switchDataPathId ^ (switchDataPathId >>> 32));
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFMatchWithSwDpid)) {
-            return false;
-        }
-        OFMatchWithSwDpid other = (OFMatchWithSwDpid) obj;
-        if (ofMatch == null) {
-            if (other.ofMatch != null) {
-                return false;
-            }
-        } else if (!ofMatch.equals(other.ofMatch)) {
-            return false;
-        }
-        if (switchDataPathId != other.switchDataPathId) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFMessage.java b/src/main/java/org/openflow/protocol/OFMessage.java
deleted file mode 100644
index 38f4e4773..000000000
--- a/src/main/java/org/openflow/protocol/OFMessage.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.concurrent.ConcurrentHashMap;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.packet.Ethernet;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.HexString;
-import org.openflow.util.U16;
-import org.openflow.util.U32;
-import org.openflow.util.U8;
-
-/**
- * The base class for all OpenFlow protocol messages. This class contains the
- * equivalent of the ofp_header which is present in all OpenFlow messages.
- *
- * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 3, 2010
- * @author Rob Sherwood (rob.sherwood@stanford.edu) - Feb 3, 2010
- */
-public class OFMessage {
-    public static final int MAXIMUM_LENGTH = (1 << 16) - 1;
-    public static byte OFP_VERSION = 0x01;
-    public static int MINIMUM_LENGTH = 8;
-
-    protected byte version;
-    protected OFType type;
-    protected short length;
-    protected int xid;
-
-    private ConcurrentHashMap<String, Object> storage;
-
-    public OFMessage() {
-        storage = null;
-        this.version = OFP_VERSION;
-    }
-
-    protected synchronized ConcurrentHashMap<String, Object> getMessageStore() {
-        if (storage == null) {
-            storage = new ConcurrentHashMap<String, Object>();;
-        }
-        return storage;
-    }
-
-    /**
-     * Get the length of this message
-     *
-     * @return
-     */
-    public short getLength() {
-        return length;
-    }
-
-    /**
-     * Get the length of this message, unsigned
-     *
-     * @return
-     */
-    public int getLengthU() {
-        return U16.f(length);
-    }
-
-    /**
-     * Set the length of this message
-     *
-     * @param length
-     */
-    public OFMessage setLength(short length) {
-        this.length = length;
-        return this;
-    }
-
-    /**
-     * Set the length of this message, unsigned
-     *
-     * @param length
-     */
-    public OFMessage setLengthU(int length) {
-        this.length = U16.t(length);
-        return this;
-    }
-
-    /**
-     * Get the type of this message
-     *
-     * @return
-     */
-    public OFType getType() {
-        return type;
-    }
-
-    /**
-     * Set the type of this message
-     *
-     * @param type
-     */
-    public void setType(OFType type) {
-        this.type = type;
-    }
-
-    /**
-     * Get the OpenFlow version of this message
-     *
-     * @return
-     */
-    public byte getVersion() {
-        return version;
-    }
-
-    /**
-     * Set the OpenFlow version of this message
-     *
-     * @param version
-     */
-    public void setVersion(byte version) {
-        this.version = version;
-    }
-
-    /**
-     * Get the transaction id of this message
-     *
-     * @return
-     */
-    public int getXid() {
-        return xid;
-    }
-
-    /**
-     * Set the transaction id of this message
-     *
-     * @param xid
-     */
-    public void setXid(int xid) {
-        this.xid = xid;
-    }
-
-    /**
-     * Read this message off the wire from the specified ByteBuffer
-     * @param data
-     */
-    public void readFrom(ChannelBuffer data) {
-        this.version = data.readByte();
-        this.type = OFType.valueOf(data.readByte());
-        this.length = data.readShort();
-        this.xid = data.readInt();
-    }
-
-    /**
-     * Write this message's binary format to the specified ByteBuffer
-     * @param data
-     */
-    public void writeTo(ChannelBuffer data) {
-        data.writeByte(version);
-        data.writeByte(type.getTypeValue());
-        data.writeShort(length);
-        data.writeInt(xid);
-    }
-
-    /**
-     * Returns a summary of the message
-     * @return "ofmsg=v=$version;t=$type:l=$len:xid=$xid"
-     */
-    @Override
-    public String toString() {
-        return "ofmsg" +
-            ":v=" + U8.f(this.getVersion()) +
-            ";t=" + this.getType() +
-            ";l=" + this.getLengthU() +
-            ";x=" + U32.f(this.getXid());
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 97;
-        int result = 1;
-        result = prime * result + length;
-        result = prime * result + ((type == null) ? 0 : type.hashCode());
-        result = prime * result + version;
-        result = prime * result + xid;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFMessage)) {
-            return false;
-        }
-        OFMessage other = (OFMessage) obj;
-        if (length != other.length) {
-            return false;
-        }
-        if (type == null) {
-            if (other.type != null) {
-                return false;
-            }
-        } else if (!type.equals(other.type)) {
-            return false;
-        }
-        if (version != other.version) {
-            return false;
-        }
-        if (xid != other.xid) {
-            return false;
-        }
-        return true;
-    }
-
-    public static String getDataAsString(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-
-        Ethernet eth;
-        StringBuffer sb =  new StringBuffer("");
-
-        DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
-        Date date = new Date();
-
-        sb.append(dateFormat.format(date));
-        sb.append("      ");
-
-        switch (msg.getType()) {
-            case PACKET_IN:
-                OFPacketIn pktIn = (OFPacketIn) msg;
-                sb.append("packet_in          [ ");
-                sb.append(sw.getStringId());
-                sb.append(" -> Controller");
-                sb.append(" ]");
-
-                sb.append("\ntotal length: ");
-                sb.append(pktIn.getTotalLength());
-                sb.append("\nin_port: ");
-                sb.append(pktIn.getInPort());
-                sb.append("\ndata_length: ");
-                sb.append(pktIn.getTotalLength() - OFPacketIn.MINIMUM_LENGTH);
-                sb.append("\nbuffer: ");
-                sb.append(pktIn.getBufferId());
-
-                // If the conext is not set by floodlight, then ignore.
-                if (cntx != null) {
-                // packet type  icmp, arp, etc.
-                    eth = IFloodlightProviderService.bcStore.get(cntx,
-                            IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-                    if (eth != null)
-                           sb.append(eth.toString());
-                }
-                break;
-
-            case PACKET_OUT:
-                OFPacketOut pktOut = (OFPacketOut) msg;
-                sb.append("packet_out         [ ");
-                sb.append("Controller -> ");
-                sb.append(HexString.toHexString(sw.getId()));
-                sb.append(" ]");
-
-                sb.append("\nin_port: ");
-                sb.append(pktOut.getInPort());
-                sb.append("\nactions_len: ");
-                sb.append(pktOut.getActionsLength());
-                if (pktOut.getActions() != null) {
-                    sb.append("\nactions: ");
-                    sb.append(pktOut.getActions().toString());
-                }
-                break;
-
-            case FLOW_MOD:
-                OFFlowMod fm = (OFFlowMod) msg;
-                sb.append("flow_mod           [ ");
-                sb.append("Controller -> ");
-                sb.append(HexString.toHexString(sw.getId()));
-                sb.append(" ]");
-
-                // If the conext is not set by floodlight, then ignore.
-                if (cntx != null) {
-                    eth = IFloodlightProviderService.bcStore.get(cntx,
-                        IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-                    if (eth != null)
-                        sb.append(eth.toString());
-                }
-
-                sb.append("\nADD: cookie: ");
-                sb.append(fm.getCookie());
-                sb.append(" idle: ");
-                sb.append(fm.getIdleTimeout());
-                sb.append(" hard: ");
-                sb.append(fm.getHardTimeout());
-                sb.append(" pri: ");
-                sb.append(fm.getPriority());
-                sb.append(" buf: ");
-                sb.append(fm.getBufferId());
-                sb.append(" flg: ");
-                sb.append(fm.getFlags());
-                if (fm.getActions() != null) {
-                    sb.append("\nactions: ");
-                    sb.append(fm.getActions().toString());
-                }
-                break;
-
-            default:
-                sb.append("[Unknown Packet]");
-        }
-
-        sb.append("\n\n");
-        return sb.toString();
-
-    }
-
-    public static byte[] getData(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-        return OFMessage.getDataAsString(sw, msg, cntx).getBytes();
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFMessageContextStore.java b/src/main/java/org/openflow/protocol/OFMessageContextStore.java
deleted file mode 100644
index b60aa1cd4..000000000
--- a/src/main/java/org/openflow/protocol/OFMessageContextStore.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.protocol.OFMessage;
-
-public class OFMessageContextStore<V> {
-    protected OFMessage msg;
-    String namespace;
-    
-    public OFMessageContextStore(OFMessage msg, String namespace) {
-        this.msg = msg;
-        this.namespace = namespace;
-    }
-    
-    @SuppressWarnings("unchecked")
-    public V get(String key) {
-        return (V)msg.getMessageStore().get(namespace + "|" + key);
-    }
-    
-    public void put(String key, V value) {
-        msg.getMessageStore().put(namespace + "|" + key, value);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFPacketIn.java b/src/main/java/org/openflow/protocol/OFPacketIn.java
deleted file mode 100644
index c37c9184c..000000000
--- a/src/main/java/org/openflow/protocol/OFPacketIn.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.util.Arrays;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-import org.openflow.util.U32;
-import org.openflow.util.U8;
-
-/**
- * Represents an ofp_packet_in
- *
- * @author David Erickson (daviderickson@cs.stanford.edu) - Feb 8, 2010
- */
-public class OFPacketIn extends OFMessage {
-    public static short MINIMUM_LENGTH = 18;
-
-    public enum OFPacketInReason {
-        NO_MATCH, ACTION
-    }
-
-    protected int bufferId;
-    protected short totalLength;
-    protected short inPort;
-    protected OFPacketInReason reason;
-    protected byte[] packetData;
-
-    public OFPacketIn() {
-        super();
-        this.type = OFType.PACKET_IN;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /**
-     * Get buffer_id
-     * @return
-     */
-    public int getBufferId() {
-        return this.bufferId;
-    }
-
-    /**
-     * Set buffer_id
-     * @param bufferId
-     */
-    public OFPacketIn setBufferId(int bufferId) {
-        this.bufferId = bufferId;
-        return this;
-    }
-
-    /**
-     * Returns the packet data
-     * @return
-     */
-    public byte[] getPacketData() {
-        return this.packetData;
-    }
-
-    /**
-     * Sets the packet data, and updates the length of this message
-     * @param packetData
-     */
-    public OFPacketIn setPacketData(byte[] packetData) {
-        this.packetData = packetData;
-        this.length = U16.t(OFPacketIn.MINIMUM_LENGTH + packetData.length);
-        return this;
-    }
-
-    /**
-     * Get in_port
-     * @return
-     */
-    public short getInPort() {
-        return this.inPort;
-    }
-
-    /**
-     * Set in_port
-     * @param inPort
-     */
-    public OFPacketIn setInPort(short inPort) {
-        this.inPort = inPort;
-        return this;
-    }
-
-    /**
-     * Get reason
-     * @return
-     */
-    public OFPacketInReason getReason() {
-        return this.reason;
-    }
-
-    /**
-     * Set reason
-     * @param reason
-     */
-    public OFPacketIn setReason(OFPacketInReason reason) {
-        this.reason = reason;
-        return this;
-    }
-
-    /**
-     * Get total_len
-     * @return
-     */
-    public short getTotalLength() {
-        return this.totalLength;
-    }
-
-    /**
-     * Set total_len
-     * @param totalLength
-     */
-    public OFPacketIn setTotalLength(short totalLength) {
-        this.totalLength = totalLength;
-        return this;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.bufferId = data.readInt();
-        this.totalLength = data.readShort();
-        this.inPort = data.readShort();
-        this.reason = OFPacketInReason.values()[U8.f(data.readByte())];
-        data.readByte(); // pad
-        this.packetData = new byte[getLengthU() - MINIMUM_LENGTH];
-        data.readBytes(this.packetData);
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeInt(bufferId);
-        data.writeShort(totalLength);
-        data.writeShort(inPort);
-        data.writeByte((byte) reason.ordinal());
-        data.writeByte((byte) 0x0); // pad
-        data.writeBytes(this.packetData);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 283;
-        int result = super.hashCode();
-        result = prime * result + bufferId;
-        result = prime * result + inPort;
-        result = prime * result + Arrays.hashCode(packetData);
-        result = prime * result + ((reason == null) ? 0 : reason.hashCode());
-        result = prime * result + totalLength;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFPacketIn)) {
-            return false;
-        }
-        OFPacketIn other = (OFPacketIn) obj;
-        if (bufferId != other.bufferId) {
-            return false;
-        }
-        if (inPort != other.inPort) {
-            return false;
-        }
-        if (!Arrays.equals(packetData, other.packetData)) {
-            return false;
-        }
-        if (reason == null) {
-            if (other.reason != null) {
-                return false;
-            }
-        } else if (!reason.equals(other.reason)) {
-            return false;
-        }
-        if (totalLength != other.totalLength) {
-            return false;
-        }
-        return true;
-    }
-
-    public String toString() {
-        String myStr = super.toString();
-        return "packetIn" +
-            ":bufferId=" + U32.f(this.bufferId) + myStr;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFPacketOut.java b/src/main/java/org/openflow/protocol/OFPacketOut.java
deleted file mode 100644
index ef4aa61f1..000000000
--- a/src/main/java/org/openflow/protocol/OFPacketOut.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.factory.OFActionFactory;
-import org.openflow.protocol.factory.OFActionFactoryAware;
-import org.openflow.util.HexString;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_packet_out message
- *
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 12, 2010
- */
-public class OFPacketOut extends OFMessage implements OFActionFactoryAware {
-    public static int MINIMUM_LENGTH = 16;
-    public static int BUFFER_ID_NONE = 0xffffffff;
-
-    protected OFActionFactory actionFactory;
-    protected int bufferId;
-    protected short inPort;
-    protected short actionsLength;
-    protected List<OFAction> actions;
-    protected byte[] packetData;
-
-    public OFPacketOut() {
-        super();
-        this.type = OFType.PACKET_OUT;
-        this.length = U16.t(MINIMUM_LENGTH);
-        this.bufferId = BUFFER_ID_NONE;
-    }
-
-    /**
-     * Get buffer_id
-     * @return
-     */
-    public int getBufferId() {
-        return this.bufferId;
-    }
-
-    /**
-     * Set buffer_id
-     * @param bufferId
-     */
-    public OFPacketOut setBufferId(int bufferId) {
-        if (packetData != null && packetData.length > 0 && bufferId != BUFFER_ID_NONE) {
-            throw new IllegalArgumentException(
-                    "PacketOut should not have both bufferId and packetData set");
-        }
-        this.bufferId = bufferId;
-        return this;
-    }
-
-    /**
-     * Returns the packet data
-     * @return
-     */
-    public byte[] getPacketData() {
-        return this.packetData;
-    }
-
-    /**
-     * Sets the packet data
-     * @param packetData
-     */
-    public OFPacketOut setPacketData(byte[] packetData) {
-        if (packetData != null && packetData.length > 0 && bufferId != BUFFER_ID_NONE) {
-            throw new IllegalArgumentException(
-                    "PacketOut should not have both bufferId and packetData set");
-        }
-        this.packetData = packetData;
-        return this;
-    }
-
-    /**
-     * Get in_port
-     * @return
-     */
-    public short getInPort() {
-        return this.inPort;
-    }
-
-    /**
-     * Set in_port
-     * @param inPort
-     */
-    public OFPacketOut setInPort(short inPort) {
-        this.inPort = inPort;
-        return this;
-    }
-
-    /**
-     * Set in_port. Convenience method using OFPort enum.
-     * @param inPort
-     */
-    public OFPacketOut setInPort(OFPort inPort) {
-        this.inPort = inPort.getValue();
-        return this;
-    }
-
-    /**
-     * Get actions_len
-     * @return
-     */
-    public short getActionsLength() {
-        return this.actionsLength;
-    }
-
-    /**
-     * Get actions_len, unsigned
-     * @return
-     */
-    public int getActionsLengthU() {
-        return U16.f(this.actionsLength);
-    }
-
-    /**
-     * Set actions_len
-     * @param actionsLength
-     */
-    public OFPacketOut setActionsLength(short actionsLength) {
-        this.actionsLength = actionsLength;
-        return this;
-    }
-
-    /**
-     * Returns the actions contained in this message
-     * @return a list of ordered OFAction objects
-     */
-    public List<OFAction> getActions() {
-        return this.actions;
-    }
-
-    /**
-     * Sets the list of actions on this message
-     * @param actions a list of ordered OFAction objects
-     */
-    public OFPacketOut setActions(List<OFAction> actions) {
-        this.actions = actions;
-        return this;
-    }
-
-    @Override
-    public void setActionFactory(OFActionFactory actionFactory) {
-        this.actionFactory = actionFactory;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.bufferId = data.readInt();
-        this.inPort = data.readShort();
-        this.actionsLength = data.readShort();
-        if ( this.actionFactory == null)
-            throw new RuntimeException("ActionFactory not set");
-        this.actions = this.actionFactory.parseActions(data, getActionsLengthU());
-        this.packetData = new byte[getLengthU() - MINIMUM_LENGTH - getActionsLengthU()];
-        data.readBytes(this.packetData);
-        validate();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        validate();
-        super.writeTo(data);
-        data.writeInt(bufferId);
-        data.writeShort(inPort);
-        data.writeShort(actionsLength);
-        for (OFAction action : actions) {
-            action.writeTo(data);
-        }
-        if (this.packetData != null)
-            data.writeBytes(this.packetData);
-    }
-
-    /** validate the invariants of this OFMessage hold */
-    public void validate() {
-        if (!((bufferId != BUFFER_ID_NONE) ^ (packetData != null && packetData.length > 0))) {
-            throw new IllegalStateException(
-                    "OFPacketOut must have exactly one of (bufferId, packetData) set (not one, not both)");
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 293;
-        int result = super.hashCode();
-        result = prime * result + ((actions == null) ? 0 : actions.hashCode());
-        result = prime * result + actionsLength;
-        result = prime * result + bufferId;
-        result = prime * result + inPort;
-        result = prime * result + Arrays.hashCode(packetData);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFPacketOut)) {
-            return false;
-        }
-        OFPacketOut other = (OFPacketOut) obj;
-        if (actions == null) {
-            if (other.actions != null) {
-                return false;
-            }
-        } else if (!actions.equals(other.actions)) {
-            return false;
-        }
-        if (actionsLength != other.actionsLength) {
-            return false;
-        }
-        if (bufferId != other.bufferId) {
-            return false;
-        }
-        if (inPort != other.inPort) {
-            return false;
-        }
-        if (!Arrays.equals(packetData, other.packetData)) {
-            return false;
-        }
-        return true;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        return "OFPacketOut [actionFactory=" + actionFactory + ", actions="
-                + actions + ", actionsLength=" + actionsLength + ", bufferId=0x"
-                + Integer.toHexString(bufferId) + ", inPort=" + inPort + ", packetData="
-                + HexString.toHexString(packetData) + "]";
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFPacketQueue.java b/src/main/java/org/openflow/protocol/OFPacketQueue.java
deleted file mode 100644
index e8de1af56..000000000
--- a/src/main/java/org/openflow/protocol/OFPacketQueue.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.protocol;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-/**
- * Represents ofp_packet_queue
- * @author Andrew Ferguson (adf@cs.brown.edu)
- */
-public class OFPacketQueue {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected int queueId;
-    protected short length;
-    protected List<OFQueueProp> properties = new ArrayList<OFQueueProp>();
-
-    public OFPacketQueue() {
-        this.queueId = -1;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    public OFPacketQueue(int queueId) {
-        this.queueId = queueId;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /**
-     * @return the queueId
-     */
-    public long getQueueId() {
-        return queueId;
-    }
-
-    /**
-     * @param queueId the queueId to set
-     */
-    public void setQueueId(int queueId) {
-        this.queueId = queueId;
-    }
-
-    /**
-     * @return the queue's properties
-     */
-    public List<OFQueueProp> getProperties() {
-        return properties;
-    }
-
-    /**
-     * @param properties the properties to set
-     */
-    public void setProperties(List<OFQueueProp> properties) {
-        this.properties = properties;
-
-        this.length = U16.t(MINIMUM_LENGTH);
-        for (OFQueueProp prop : properties) {
-            this.length += prop.getLength();
-        }
-    }
-
-    /**
-     * @return the length
-     */
-    public short getLength() {
-        return length;
-    }
-
-    public void readFrom(ChannelBuffer data) {
-        this.queueId = data.readInt();
-        this.length = data.readShort();
-        data.readShort(); // pad
-
-        int availLength = (this.length - MINIMUM_LENGTH);
-        this.properties.clear();
-
-        while (availLength > 0) {
-            OFQueueProp prop = new OFQueueProp();
-            prop.readFrom(data);
-            properties.add(prop);
-            availLength -= prop.getLength();
-        }
-    }
-
-    public void writeTo(ChannelBuffer data) {
-        data.writeInt(queueId);
-        data.writeShort(length);
-        data.writeShort(0); // pad
-
-        for (OFQueueProp prop : properties) {
-            prop.writeTo(data);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 359;
-        int result = super.hashCode();
-        result = prime * result + queueId;
-        result = prime * result + length;
-        result = prime * result + properties.hashCode();
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFPacketQueue)) {
-            return false;
-        }
-        OFPacketQueue other = (OFPacketQueue) obj;
-        if (queueId != other.queueId) {
-            return false;
-        }
-        if (! properties.equals(other.properties)) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFPhysicalPort.java b/src/main/java/org/openflow/protocol/OFPhysicalPort.java
deleted file mode 100644
index 88de8f657..000000000
--- a/src/main/java/org/openflow/protocol/OFPhysicalPort.java
+++ /dev/null
@@ -1,614 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol;
-
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-
-import net.floodlightcontroller.core.web.serializers.ByteArrayMACSerializer;
-import net.floodlightcontroller.core.web.serializers.UShortSerializer;
-import net.floodlightcontroller.util.EnumBitmaps;
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.HexString;
-
-/**
- * Represents ofp_phy_port
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 25, 2010
- */
-public class OFPhysicalPort {
-    public final static int MINIMUM_LENGTH = 48;
-    public final static int OFP_ETH_ALEN = 6;
-
-    public enum OFPortConfig implements EnumBitmaps.BitmapableEnum {
-        OFPPC_PORT_DOWN    (1 << 0) {
-            @Override
-            public String toString() {
-                return "port-down (0x1)";
-            }
-        },
-        OFPPC_NO_STP       (1 << 1) {
-            @Override
-            public String toString() {
-                return "no-stp (0x2)";
-            }
-        },
-        OFPPC_NO_RECV      (1 << 2) {
-            @Override
-            public String toString() {
-                return "no-recv (0x4)";
-            }
-        },
-        OFPPC_NO_RECV_STP  (1 << 3) {
-            @Override
-            public String toString() {
-                return "no-recv-stp (0x8)";
-            }
-        },
-        OFPPC_NO_FLOOD     (1 << 4) {
-            @Override
-            public String toString() {
-                return "no-flood (0x10)";
-            }
-        },
-        OFPPC_NO_FWD       (1 << 5) {
-            @Override
-            public String toString() {
-                return "no-fwd (0x20)";
-            }
-        },
-        OFPPC_NO_PACKET_IN (1 << 6) {
-            @Override
-            public String toString() {
-                return "no-pkt-in (0x40)";
-            }
-        },
-        OFPPC_BSN_MIRROR_DEST (1 << 31) {
-            @Override
-            public String toString() {
-                return "bsn-mirror-dest (0x80000000)";
-            }
-        };
-
-
-        protected int value;
-
-        private OFPortConfig(int value) {
-            this.value = value;
-        }
-
-        /**
-         * @return the value
-         */
-        @Override
-        public int getValue() {
-            return value;
-        }
-    }
-
-    public enum OFPortState {
-        OFPPS_LINK_DOWN   (1 << 0, false) {
-            @Override
-            public String toString() {
-                return "link-down (0x1)";
-            }
-        },
-        OFPPS_STP_LISTEN  (0 << 8, true) {
-            @Override
-            public String toString() {
-                return "listen (0x0)";
-            }
-        },
-        OFPPS_STP_LEARN   (1 << 8, true) {
-            @Override
-            public String toString() {
-                return "learn-no-relay (0x100)";
-            }
-        },
-        OFPPS_STP_FORWARD (2 << 8, true) {
-            @Override
-            public String toString() {
-                return "forward (0x200)";
-            }
-        },
-        OFPPS_STP_BLOCK   (3 << 8, true) {
-            @Override
-            public String toString() {
-                return "block-broadcast (0x300)";
-            }
-        },
-        OFPPS_STP_MASK    (3 << 8, false) { // used for STP but not an STP state
-            @Override
-            public String toString() {
-                return "block-broadcast (0x300)";
-            }
-        };
-
-        protected int value;
-        protected boolean isStpState;
-
-        private OFPortState(int value, boolean isStpState) {
-            this.value = value;
-            this.isStpState = isStpState;
-        }
-
-        /**
-         * Returns true if this constants represents one of the four STP
-         * states
-         * @return
-         */
-        public boolean isStpState() {
-            return isStpState;
-        }
-
-        /**
-         * return the STP state represented by the given integer.
-         * the returned value will have isStpState() == true
-         * @param state
-         * @return
-         */
-        public static OFPortState getStpState(int state) {
-            // this ain't pretty
-            state = state & OFPortState.OFPPS_STP_MASK.getValue();
-            for (OFPortState s: OFPortState.values()) {
-                if (!s.isStpState())
-                    continue;
-                if (state == s.getValue())
-                    return s;
-            }
-            return null; // will never happen
-        }
-
-        public static boolean isPortDown(int state) {
-            if ((state & OFPPS_LINK_DOWN.getValue()) != 0)
-                return true;
-            else
-                return false;
-        }
-
-        /**
-         * @return the value
-         */
-        public int getValue() {
-            return value;
-        }
-    }
-
-    /**
-     * Represents the speed of a port
-     */
-    public enum PortSpeed {
-        /** no speed set */
-        SPEED_NONE(0),
-        SPEED_10MB(10),
-        SPEED_100MB(100),
-        SPEED_1GB(1000),
-        SPEED_10GB(10000);
-
-        private long speedInBps;
-        private PortSpeed(int speedInMbps) {
-            this.speedInBps = speedInMbps * 1000*1000;
-        }
-
-        public long getSpeedBps() {
-            return this.speedInBps;
-        }
-
-        public static PortSpeed max(PortSpeed s1, PortSpeed s2) {
-            return (s1.getSpeedBps() > s2.getSpeedBps()) ? s1 : s2;
-        }
-
-        public static PortSpeed min(PortSpeed s1, PortSpeed s2) {
-            return (s1.getSpeedBps() < s2.getSpeedBps()) ? s1 : s2;
-        }
-    }
-
-    public enum OFPortFeatures implements EnumBitmaps.BitmapableEnum {
-        OFPPF_10MB_HD    (1 << 0, PortSpeed.SPEED_10MB) {
-            @Override
-            public String toString() {
-                return "10mb-hd (0x1)";
-            }
-        },
-        OFPPF_10MB_FD    (1 << 1, PortSpeed.SPEED_10MB) {
-            @Override
-            public String toString() {
-                return "10mb-fd (0x2)";
-            }
-        },
-        OFPPF_100MB_HD   (1 << 2, PortSpeed.SPEED_100MB) {
-            @Override
-            public String toString() {
-                return "100mb-hd (0x4)";
-            }
-        },
-        OFPPF_100MB_FD   (1 << 3, PortSpeed.SPEED_100MB) {
-            @Override
-            public String toString() {
-                return "100mb-fd (0x8)";
-            }
-        },
-        OFPPF_1GB_HD     (1 << 4, PortSpeed.SPEED_1GB) {
-            @Override
-            public String toString() {
-                return "1gb-hd (0x10)";
-            }
-        },
-        OFPPF_1GB_FD     (1 << 5, PortSpeed.SPEED_1GB) {
-            @Override
-            public String toString() {
-                return "1gb-fd (0x20)";
-            }
-        },
-        OFPPF_10GB_FD    (1 << 6, PortSpeed.SPEED_10GB) {
-            @Override
-            public String toString() {
-                return "10gb-fd (0x40)";
-            }
-        },
-        OFPPF_COPPER     (1 << 7, PortSpeed.SPEED_NONE) {
-            @Override
-            public String toString() {
-                return "copper (0x80)";
-            }
-        },
-        OFPPF_FIBER      (1 << 8, PortSpeed.SPEED_NONE) {
-            @Override
-            public String toString() {
-                return "fiber (0x100)";
-            }
-        },
-        OFPPF_AUTONEG    (1 << 9, PortSpeed.SPEED_NONE) {
-            @Override
-            public String toString() {
-                return "autoneg (0x200)";
-            }
-        },
-        OFPPF_PAUSE      (1 << 10, PortSpeed.SPEED_NONE) {
-            @Override
-            public String toString() {
-                return "pause (0x400)";
-            }
-        },
-        OFPPF_PAUSE_ASYM (1 << 11, PortSpeed.SPEED_NONE) {
-            @Override
-            public String toString() {
-                return "pause-asym (0x800)";
-            }
-        };
-
-        protected int value;
-        protected PortSpeed speed;
-
-        private OFPortFeatures(int value, PortSpeed speed) {
-            this.value = value;
-            if (speed == null)
-                throw new NullPointerException();
-            this.speed = speed;
-        }
-
-        /**
-         * @return the bitmap value for this constant
-         */
-        @Override
-        public int getValue() {
-            return value;
-        }
-
-        /**
-         * @return the port speed associated with this constant. If the
-         * constant doesn't represent a port speed it returns SPEED_NONE
-         */
-        public PortSpeed getSpeed() {
-            return speed;
-        }
-    }
-
-    protected short portNumber;
-    protected byte[] hardwareAddress;
-    protected String name;
-    protected int config;
-    protected int state;
-    protected int currentFeatures;
-    protected int advertisedFeatures;
-    protected int supportedFeatures;
-    protected int peerFeatures;
-
-    /**
-     * @return the portNumber
-     */
-    @JsonSerialize(using=UShortSerializer.class)
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param portNumber the portNumber to set
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-    /**
-     * @return the hardwareAddress
-     */
-    @JsonSerialize(using=ByteArrayMACSerializer.class)
-    public byte[] getHardwareAddress() {
-        return hardwareAddress;
-    }
-
-    /**
-     * @param hardwareAddress the hardwareAddress to set
-     */
-    public void setHardwareAddress(byte[] hardwareAddress) {
-        if (hardwareAddress.length != OFP_ETH_ALEN)
-            throw new RuntimeException("Hardware address must have length "
-                    + OFP_ETH_ALEN);
-        this.hardwareAddress = hardwareAddress;
-    }
-
-    /**
-     * @return the name
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * @param name the name to set
-     */
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    /**
-     * @return the config
-     */
-    public int getConfig() {
-        return config;
-    }
-
-    /**
-     * @param config the config to set
-     */
-    public void setConfig(int config) {
-        this.config = config;
-    }
-
-    /**
-     * @return the state
-     */
-    public int getState() {
-        return state;
-    }
-
-    /**
-     * @param state the state to set
-     */
-    public void setState(int state) {
-        this.state = state;
-    }
-
-    /**
-     * @return the currentFeatures
-     */
-    public int getCurrentFeatures() {
-        return currentFeatures;
-    }
-
-    /**
-     * @param currentFeatures the currentFeatures to set
-     */
-    public void setCurrentFeatures(int currentFeatures) {
-        this.currentFeatures = currentFeatures;
-    }
-
-    /**
-     * @return the advertisedFeatures
-     */
-    public int getAdvertisedFeatures() {
-        return advertisedFeatures;
-    }
-
-    /**
-     * @param advertisedFeatures the advertisedFeatures to set
-     */
-    public void setAdvertisedFeatures(int advertisedFeatures) {
-        this.advertisedFeatures = advertisedFeatures;
-    }
-
-    /**
-     * @return the supportedFeatures
-     */
-    public int getSupportedFeatures() {
-        return supportedFeatures;
-    }
-
-    /**
-     * @param supportedFeatures the supportedFeatures to set
-     */
-    public void setSupportedFeatures(int supportedFeatures) {
-        this.supportedFeatures = supportedFeatures;
-    }
-
-    /**
-     * @return the peerFeatures
-     */
-    public int getPeerFeatures() {
-        return peerFeatures;
-    }
-
-    /**
-     * @param peerFeatures the peerFeatures to set
-     */
-    public void setPeerFeatures(int peerFeatures) {
-        this.peerFeatures = peerFeatures;
-    }
-
-    /**
-     * Read this message off the wire from the specified ByteBuffer
-     * @param data
-     */
-    public void readFrom(ChannelBuffer data) {
-        this.portNumber = data.readShort();
-        if (this.hardwareAddress == null)
-            this.hardwareAddress = new byte[OFP_ETH_ALEN];
-        data.readBytes(this.hardwareAddress);
-        byte[] name = new byte[16];
-        data.readBytes(name);
-        // find the first index of 0
-        int index = 0;
-        for (byte b : name) {
-            if (0 == b)
-                break;
-            ++index;
-        }
-        this.name = new String(Arrays.copyOf(name, index),
-                Charset.forName("ascii"));
-        this.config = data.readInt();
-        this.state = data.readInt();
-        this.currentFeatures = data.readInt();
-        this.advertisedFeatures = data.readInt();
-        this.supportedFeatures = data.readInt();
-        this.peerFeatures = data.readInt();
-    }
-
-    /**
-     * Write this message's binary format to the specified ByteBuffer
-     * @param data
-     */
-    public void writeTo(ChannelBuffer data) {
-        data.writeShort(this.portNumber);
-        data.writeBytes(hardwareAddress);
-        try {
-            byte[] name = this.name.getBytes("ASCII");
-            if (name.length < 16) {
-                data.writeBytes(name);
-                for (int i = name.length; i < 16; ++i) {
-                    data.writeByte((byte) 0);
-                }
-            } else {
-                data.writeBytes(name, 0, 15);
-                data.writeByte((byte) 0);
-            }
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException(e);
-        }
-        data.writeInt(this.config);
-        data.writeInt(this.state);
-        data.writeInt(this.currentFeatures);
-        data.writeInt(this.advertisedFeatures);
-        data.writeInt(this.supportedFeatures);
-        data.writeInt(this.peerFeatures);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 307;
-        int result = 1;
-        result = prime * result + advertisedFeatures;
-        result = prime * result + config;
-        result = prime * result + currentFeatures;
-        result = prime * result + Arrays.hashCode(hardwareAddress);
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result + peerFeatures;
-        result = prime * result + portNumber;
-        result = prime * result + state;
-        result = prime * result + supportedFeatures;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFPhysicalPort)) {
-            return false;
-        }
-        OFPhysicalPort other = (OFPhysicalPort) obj;
-        if (advertisedFeatures != other.advertisedFeatures) {
-            return false;
-        }
-        if (config != other.config) {
-            return false;
-        }
-        if (currentFeatures != other.currentFeatures) {
-            return false;
-        }
-        if (!Arrays.equals(hardwareAddress, other.hardwareAddress)) {
-            return false;
-        }
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
-        if (peerFeatures != other.peerFeatures) {
-            return false;
-        }
-        if (portNumber != other.portNumber) {
-            return false;
-        }
-        if (state != other.state) {
-            return false;
-        }
-        if (supportedFeatures != other.supportedFeatures) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        String linkState, linkSpeed;
-        if ((state & OFPortState.OFPPS_LINK_DOWN.getValue()) != 0) {
-            linkState = "down";
-        } else {
-            linkState = "up";
-        }
-        if ((currentFeatures & OFPortFeatures.OFPPF_10GB_FD.getValue()) != 0) {
-            linkSpeed = "10G";
-        } else if ((currentFeatures & OFPortFeatures.OFPPF_1GB_FD.getValue()) != 0) {
-            linkSpeed = "1G";
-        } else if ((currentFeatures & OFPortFeatures.OFPPF_1GB_HD.getValue()) != 0) {
-            linkSpeed = "1G(half-duplex)";
-        } else if ((currentFeatures & OFPortFeatures.OFPPF_100MB_FD.getValue()) != 0) {
-            linkSpeed = "100M";
-        } else if ((currentFeatures & OFPortFeatures.OFPPF_100MB_HD.getValue()) != 0) {
-            linkSpeed = "100M(half-duplex)";
-        } else if ((currentFeatures & OFPortFeatures.OFPPF_10MB_FD.getValue()) != 0) {
-            linkSpeed = "10M";
-        } else if ((currentFeatures & OFPortFeatures.OFPPF_10MB_HD.getValue()) != 0) {
-            linkSpeed = "10M(half-duplex)";
-        } else {
-            linkSpeed = "unknown";
-        }
-        return "port " + name + " (" +  portNumber + ")" +
-               ", mac " + HexString.toHexString(hardwareAddress) +
-               ", state " + linkState +
-               ", speed " + linkSpeed;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFPort.java b/src/main/java/org/openflow/protocol/OFPort.java
deleted file mode 100644
index 93301bcb0..000000000
--- a/src/main/java/org/openflow/protocol/OFPort.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-public enum OFPort {
-    OFPP_MAX                ((short)0xff00),
-    OFPP_IN_PORT            ((short)0xfff8),
-    OFPP_TABLE              ((short)0xfff9),
-    OFPP_NORMAL             ((short)0xfffa),
-    OFPP_FLOOD              ((short)0xfffb),
-    OFPP_ALL                ((short)0xfffc),
-    OFPP_CONTROLLER         ((short)0xfffd),
-    OFPP_LOCAL              ((short)0xfffe),
-    OFPP_NONE               ((short)0xffff);
-
-    protected short value;
-
-    private OFPort(short value) {
-        this.value = value;
-    }
-
-    /**
-     * @return the value
-     */
-    public short getValue() {
-        return value;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFPortMod.java b/src/main/java/org/openflow/protocol/OFPortMod.java
deleted file mode 100644
index 876e85670..000000000
--- a/src/main/java/org/openflow/protocol/OFPortMod.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.util.Arrays;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_port_mod message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFPortMod extends OFMessage {
-    public static int MINIMUM_LENGTH = 32;
-
-    protected short portNumber;
-    protected byte[] hardwareAddress;
-    protected int config;
-    protected int mask;
-    protected int advertise;
-
-    public OFPortMod() {
-        super();
-        this.type = OFType.PORT_MOD;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /**
-     * @return the portNumber
-     */
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param portNumber the portNumber to set
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-    /**
-     * @return the hardwareAddress
-     */
-    public byte[] getHardwareAddress() {
-        return hardwareAddress;
-    }
-
-    /**
-     * @param hardwareAddress the hardwareAddress to set
-     */
-    public void setHardwareAddress(byte[] hardwareAddress) {
-        if (hardwareAddress.length != OFPhysicalPort.OFP_ETH_ALEN)
-            throw new RuntimeException("Hardware address must have length "
-                    + OFPhysicalPort.OFP_ETH_ALEN);
-        this.hardwareAddress = hardwareAddress;
-    }
-
-    /**
-     * @return the config
-     */
-    public int getConfig() {
-        return config;
-    }
-
-    /**
-     * @param config the config to set
-     */
-    public void setConfig(int config) {
-        this.config = config;
-    }
-
-    /**
-     * @return the mask
-     */
-    public int getMask() {
-        return mask;
-    }
-
-    /**
-     * @param mask the mask to set
-     */
-    public void setMask(int mask) {
-        this.mask = mask;
-    }
-
-    /**
-     * @return the advertise
-     */
-    public int getAdvertise() {
-        return advertise;
-    }
-
-    /**
-     * @param advertise the advertise to set
-     */
-    public void setAdvertise(int advertise) {
-        this.advertise = advertise;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.portNumber = data.readShort();
-        if (this.hardwareAddress == null)
-            this.hardwareAddress = new byte[OFPhysicalPort.OFP_ETH_ALEN];
-        data.readBytes(this.hardwareAddress);
-        this.config = data.readInt();
-        this.mask = data.readInt();
-        this.advertise = data.readInt();
-        data.readInt(); // pad
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.portNumber);
-        data.writeBytes(this.hardwareAddress);
-        data.writeInt(this.config);
-        data.writeInt(this.mask);
-        data.writeInt(this.advertise);
-        data.writeInt(0); // pad
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 311;
-        int result = super.hashCode();
-        result = prime * result + advertise;
-        result = prime * result + config;
-        result = prime * result + Arrays.hashCode(hardwareAddress);
-        result = prime * result + mask;
-        result = prime * result + portNumber;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFPortMod)) {
-            return false;
-        }
-        OFPortMod other = (OFPortMod) obj;
-        if (advertise != other.advertise) {
-            return false;
-        }
-        if (config != other.config) {
-            return false;
-        }
-        if (!Arrays.equals(hardwareAddress, other.hardwareAddress)) {
-            return false;
-        }
-        if (mask != other.mask) {
-            return false;
-        }
-        if (portNumber != other.portNumber) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFPortStatus.java b/src/main/java/org/openflow/protocol/OFPortStatus.java
deleted file mode 100644
index b7a3158ce..000000000
--- a/src/main/java/org/openflow/protocol/OFPortStatus.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_port_status message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFPortStatus extends OFMessage {
-    public static int MINIMUM_LENGTH = 64;
-
-    public enum OFPortReason {
-        OFPPR_ADD((byte)0),
-        OFPPR_DELETE((byte)1),
-        OFPPR_MODIFY((byte)2);
-
-        private byte reason;
-
-        private OFPortReason(byte reason) {
-            this.reason = reason;
-        }
-
-        public byte getReasonCode() {
-            return this.reason;
-        }
-
-        public static OFPortReason fromReasonCode(byte reason) {
-            for (OFPortReason r: OFPortReason.values()) {
-                if (r.getReasonCode() == reason)
-                    return r;
-            }
-            return null;
-        }
-    }
-
-    protected byte reason;
-    protected OFPhysicalPort desc;
-
-    /**
-     * @return the reason
-     */
-    public byte getReason() {
-        return reason;
-    }
-
-    /**
-     * @param reason the reason to set
-     */
-    public void setReason(byte reason) {
-        this.reason = reason;
-    }
-
-    /**
-     * @return the desc
-     */
-    public OFPhysicalPort getDesc() {
-        return desc;
-    }
-
-    /**
-     * @param desc the desc to set
-     */
-    public void setDesc(OFPhysicalPort desc) {
-        this.desc = desc;
-    }
-
-    public OFPortStatus() {
-        super();
-        this.type = OFType.PORT_STATUS;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.reason = data.readByte();
-        data.readerIndex(data.readerIndex() + 7); // skip 7 bytes of padding
-        if (this.desc == null)
-            this.desc = new OFPhysicalPort();
-        this.desc.readFrom(data);
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeByte(this.reason);
-        for (int i = 0; i < 7; ++i)
-            data.writeByte((byte) 0);
-        this.desc.writeTo(data);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 313;
-        int result = super.hashCode();
-        result = prime * result + ((desc == null) ? 0 : desc.hashCode());
-        result = prime * result + reason;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFPortStatus)) {
-            return false;
-        }
-        OFPortStatus other = (OFPortStatus) obj;
-        if (desc == null) {
-            if (other.desc != null) {
-                return false;
-            }
-        } else if (!desc.equals(other.desc)) {
-            return false;
-        }
-        if (reason != other.reason) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java b/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java
deleted file mode 100644
index 62be90d59..000000000
--- a/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.protocol;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_queue_get_config_request message
- * @author Andrew Ferguson (adf@cs.brown.edu)
- */
-public class OFQueueGetConfigReply extends OFMessage {
-    public static int MINIMUM_LENGTH = 16;
-
-    protected short portNumber;
-    protected List<OFPacketQueue> queues = new ArrayList<OFPacketQueue>();
-
-    public OFQueueGetConfigReply() {
-        super();
-        this.type = OFType.QUEUE_GET_CONFIG_REPLY;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /**
-     * @return the portNumber
-     */
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param portNumber the portNumber to set
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-    /**
-     * @return the port's queues
-     */
-    public List<OFPacketQueue> getQueues() {
-        return queues;
-    }
-
-    /**
-     * @param queues the queues to set
-     */
-    public void setQueues(List<OFPacketQueue> queues) {
-        this.queues.clear();
-        this.queues.addAll(queues);
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.portNumber = data.readShort();
-        data.readInt();   // pad
-        data.readShort(); // pad
-
-        int availLength = (this.length - MINIMUM_LENGTH);
-        this.queues.clear();
-
-        while (availLength > 0) {
-            OFPacketQueue queue = new OFPacketQueue();
-            queue.readFrom(data);
-            queues.add(queue);
-            availLength -= queue.getLength();
-        }
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.portNumber);
-        data.writeInt(0);   // pad
-        data.writeShort(0); // pad
-
-        for (OFPacketQueue queue : queues) {
-            queue.writeTo(data);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 349;
-        int result = super.hashCode();
-        result = prime * result + portNumber;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFQueueGetConfigReply)) {
-            return false;
-        }
-        OFQueueGetConfigReply other = (OFQueueGetConfigReply) obj;
-        if (portNumber != other.portNumber) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java b/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java
deleted file mode 100644
index cbb4a3734..000000000
--- a/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.protocol;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_queue_get_config_request message
- * @author Andrew Ferguson (adf@cs.brown.edu)
- */
-public class OFQueueGetConfigRequest extends OFMessage {
-    public static int MINIMUM_LENGTH = 12;
-
-    protected short portNumber;
-
-    public OFQueueGetConfigRequest(short portNumber) {
-        super();
-        this.type = OFType.QUEUE_GET_CONFIG_REQUEST;
-        this.length = U16.t(MINIMUM_LENGTH);
-        this.portNumber = portNumber;
-    }
-
-    public OFQueueGetConfigRequest() {
-        this((short) 0);
-    }
-
-    /**
-     * @return the portNumber
-     */
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param portNumber the portNumber to set
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.portNumber = data.readShort();
-        data.readShort(); // pad
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.portNumber);
-        data.writeShort(0); // pad
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 347;
-        int result = super.hashCode();
-        result = prime * result + portNumber;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFQueueGetConfigRequest)) {
-            return false;
-        }
-        OFQueueGetConfigRequest other = (OFQueueGetConfigRequest) obj;
-        if (portNumber != other.portNumber) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFQueueProp.java b/src/main/java/org/openflow/protocol/OFQueueProp.java
deleted file mode 100644
index 2e12224bb..000000000
--- a/src/main/java/org/openflow/protocol/OFQueueProp.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.protocol;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-public class OFQueueProp {
-    private int NONE_MINIMUM_LENGTH = 8;
-    private int RATE_MINIMUM_LENGTH = 16;
-
-    public enum OFQueuePropType {
-        OFPQT_NONE       (0),
-        OFPQT_MIN_RATE   (1),
-        OFPQT_MAX_RATE   (2);
-
-        protected int value;
-
-        private OFQueuePropType(int value) {
-            this.value = value;
-        }
-
-        /**
-         * @return the value
-         */
-        public int getValue() {
-            return value;
-        }
-
-        public static OFQueuePropType fromShort(short x) {
-            switch (x) {
-                case 0:
-                    return OFPQT_NONE;
-                case 1:
-                    return OFPQT_MIN_RATE;
-                case 2:
-                    return OFPQT_MAX_RATE;
-            }
-            return null;
-        }
-    }
-
-    protected OFQueuePropType type;
-    protected short length;
-    protected short rate = -1; // not valid if type == OFPQT_NONE
-
-    public OFQueueProp() {
-        this.type = OFQueuePropType.OFPQT_NONE;
-        this.length = U16.t(NONE_MINIMUM_LENGTH);
-    }
-
-    /**
-     * @return the type
-     */
-    public OFQueuePropType getType() {
-        return type;
-    }
-
-    /**
-     * @param type the type to set
-     */
-    public void setType(OFQueuePropType type) {
-        this.type = type;
-
-        switch (type) {
-            case OFPQT_NONE:
-                this.length = U16.t(NONE_MINIMUM_LENGTH);
-                break;
-            case OFPQT_MIN_RATE:
-                this.length = U16.t(RATE_MINIMUM_LENGTH);
-                break;
-            case OFPQT_MAX_RATE:
-                this.length = U16.t(RATE_MINIMUM_LENGTH);
-                break;
-        }
-    }
-
-    /**
-     * @return the rate
-     */
-    public short getRate() {
-        return rate;
-    }
-
-    /**
-     * @param rate the rate to set
-     */
-    public void setRate(short rate) {
-        this.rate = rate;
-    }
-
-    /**
-     * @return the length
-     */
-    public short getLength() {
-        return length;
-    }
-
-    public void readFrom(ChannelBuffer data) {
-        this.type = OFQueuePropType.fromShort(data.readShort());
-        this.length = data.readShort();
-        data.readInt(); // pad
-
-        if (this.type == OFQueuePropType.OFPQT_MIN_RATE ||
-            this.type == OFQueuePropType.OFPQT_MAX_RATE) {
-            assert(this.length == RATE_MINIMUM_LENGTH);
-
-            this.rate = data.readShort();
-            data.readInt(); // pad
-            data.readShort(); // pad
-        } else {
-            assert(this.length == NONE_MINIMUM_LENGTH);
-        }
-    }
-
-    public void writeTo(ChannelBuffer data) {
-        data.writeShort(this.type.getValue());
-        data.writeShort(this.length);
-        data.writeInt(0); // pad
-
-        if (this.type == OFQueuePropType.OFPQT_MIN_RATE ||
-            this.type == OFQueuePropType.OFPQT_MAX_RATE) {
-            data.writeShort(this.rate);
-            data.writeInt(0); // pad
-            data.writeShort(0); // pad
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 353;
-        int result = super.hashCode();
-        result = prime * result + type.getValue();
-        result = prime * result + rate;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFQueueProp)) {
-            return false;
-        }
-        OFQueueProp other = (OFQueueProp) obj;
-        if (type != other.type) {
-            return false;
-        }
-        if (type == OFQueuePropType.OFPQT_MIN_RATE ||
-            type == OFQueuePropType.OFPQT_MAX_RATE) {
-            if (rate != other.rate) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFSetConfig.java b/src/main/java/org/openflow/protocol/OFSetConfig.java
deleted file mode 100644
index 4b2356476..000000000
--- a/src/main/java/org/openflow/protocol/OFSetConfig.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-/**
- * Represents an OFPT_SET_CONFIG type message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFSetConfig extends OFSwitchConfig {
-    public OFSetConfig() {
-        super();
-        this.type = OFType.SET_CONFIG;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java b/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java
deleted file mode 100644
index e5a9c01e0..000000000
--- a/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol;
-
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.factory.OFStatisticsFactory;
-import org.openflow.protocol.factory.OFStatisticsFactoryAware;
-import org.openflow.protocol.statistics.OFStatistics;
-import org.openflow.protocol.statistics.OFStatisticsType;
-
-
-/**
- * Base class for statistics requests/replies
- *
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 27, 2010
- */
-public abstract class OFStatisticsMessageBase extends OFMessage implements
-        OFStatisticsFactoryAware {
-    public static int MINIMUM_LENGTH = 12;
-
-    protected OFStatisticsFactory statisticsFactory;
-    protected OFStatisticsType statisticType;
-    protected short flags;
-
-    // TODO: this should be List<? extends OFStatistics>, to
-    // allow for type safe assignments of lists of specific message
-    protected List<? extends OFStatistics> statistics;
-
-    /**
-     * @return the statisticType
-     */
-    public OFStatisticsType getStatisticType() {
-        return statisticType;
-    }
-
-    /**
-     * @param statisticType the statisticType to set
-     */
-    public void setStatisticType(OFStatisticsType statisticType) {
-        this.statisticType = statisticType;
-    }
-
-    /**
-     * @return the flags
-     */
-    public short getFlags() {
-        return flags;
-    }
-
-    /**
-     * @param flags the flags to set
-     */
-    public void setFlags(short flags) {
-        this.flags = flags;
-    }
-
-    /**
-     * @return the statistics
-     */
-    public List<? extends OFStatistics> getStatistics() {
-        return statistics;
-    }
-
-    /**
-     * return the first statistics request in the list of statistics, for
-     * statistics messages that expect exactly one message in their body (e.g.,
-     * flow stats request, port statsrequest)
-     *
-     * @return the first and only element in the list of statistics
-     * @throw IllegalArgumentException if the list does not contain exactly one
-     *        element
-     */
-    public OFStatistics getFirstStatistics() {
-        if (statistics == null ) {
-            throw new IllegalArgumentException("Invariant violation: statistics message of type "+statisticType+" is null");
-        }
-        if (statistics.size() != 1) {
-            throw new IllegalArgumentException("Invariant violation: statistics message of type "+statisticType+" contains "+statistics.size() +" statreq/reply messages in its body (should be 1)");
-        }
-
-        return statistics.get(0);
-    }
-
-    /**
-     * @param statistics the statistics to set
-     */
-    public void setStatistics(List<? extends OFStatistics> statistics) {
-        this.statistics = statistics;
-    }
-
-    @Override
-    public void setStatisticsFactory(OFStatisticsFactory statisticsFactory) {
-        this.statisticsFactory = statisticsFactory;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.statisticType = OFStatisticsType.valueOf(data.readShort(), this
-                .getType());
-        this.flags = data.readShort();
-        if (this.statisticsFactory == null)
-            throw new RuntimeException("OFStatisticsFactory not set");
-        this.statistics = statisticsFactory.parseStatistics(this.getType(),
-                this.statisticType, data, super.getLengthU() - MINIMUM_LENGTH);
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.statisticType.getTypeValue());
-        data.writeShort(this.flags);
-        if (this.statistics != null) {
-            for (OFStatistics statistic : this.statistics) {
-                statistic.writeTo(data);
-            }
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 317;
-        int result = super.hashCode();
-        result = prime * result + flags;
-        result = prime * result
-                + ((statisticType == null) ? 0 : statisticType.hashCode());
-        result = prime * result
-                + ((statistics == null) ? 0 : statistics.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFStatisticsMessageBase)) {
-            return false;
-        }
-        OFStatisticsMessageBase other = (OFStatisticsMessageBase) obj;
-        if (flags != other.flags) {
-            return false;
-        }
-        if (statisticType == null) {
-            if (other.statisticType != null) {
-                return false;
-            }
-        } else if (!statisticType.equals(other.statisticType)) {
-            return false;
-        }
-        if (statistics == null) {
-            if (other.statistics != null) {
-                return false;
-            }
-        } else if (!statistics.equals(other.statistics)) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFStatisticsReply.java b/src/main/java/org/openflow/protocol/OFStatisticsReply.java
deleted file mode 100644
index ddc726742..000000000
--- a/src/main/java/org/openflow/protocol/OFStatisticsReply.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_stats_reply message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFStatisticsReply extends OFStatisticsMessageBase {
-    public enum OFStatisticsReplyFlags {
-        REPLY_MORE      (1 << 0);
-
-        protected short type;
-
-        OFStatisticsReplyFlags(int type) {
-            this.type = (short) type;
-        }
-
-        public short getTypeValue() {
-            return type;
-        }
-    }
-
-    public OFStatisticsReply() {
-        super();
-        this.type = OFType.STATS_REPLY;
-        this.length = U16.t(OFStatisticsMessageBase.MINIMUM_LENGTH);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFStatisticsRequest.java b/src/main/java/org/openflow/protocol/OFStatisticsRequest.java
deleted file mode 100644
index d1d8010e9..000000000
--- a/src/main/java/org/openflow/protocol/OFStatisticsRequest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_stats_request message
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFStatisticsRequest extends OFStatisticsMessageBase {
-    public OFStatisticsRequest() {
-        super();
-        this.type = OFType.STATS_REQUEST;
-        this.length = U16.t(OFStatisticsMessageBase.MINIMUM_LENGTH);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFSwitchConfig.java b/src/main/java/org/openflow/protocol/OFSwitchConfig.java
deleted file mode 100644
index e04e3fa60..000000000
--- a/src/main/java/org/openflow/protocol/OFSwitchConfig.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Base class representing ofp_switch_config based messages
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public abstract class OFSwitchConfig extends OFMessage {
-    public static int MINIMUM_LENGTH = 12;
-
-    public enum OFConfigFlags {
-        OFPC_FRAG_NORMAL,
-        OFPC_FRAG_DROP,
-        OFPC_FRAG_REASM,
-        OFPC_FRAG_MASK
-    }
-
-    protected short flags;
-    protected short missSendLength;
-
-    public OFSwitchConfig() {
-        super();
-        super.setLengthU(MINIMUM_LENGTH);
-    }
-
-    /**
-     * @return the flags
-     */
-    public short getFlags() {
-        return flags;
-    }
-
-    /**
-     * @param flags the flags to set
-     */
-    public OFSwitchConfig setFlags(short flags) {
-        this.flags = flags;
-        return this;
-    }
-
-    /**
-     * @return the missSendLength
-     */
-    public short getMissSendLength() {
-        return missSendLength;
-    }
-
-    /**
-     * @param missSendLength the missSendLength to set
-     */
-    public OFSwitchConfig setMissSendLength(short missSendLength) {
-        this.missSendLength = missSendLength;
-        return this;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.flags = data.readShort();
-        this.missSendLength = data.readShort();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.flags);
-        data.writeShort(this.missSendLength);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 331;
-        int result = super.hashCode();
-        result = prime * result + flags;
-        result = prime * result + missSendLength;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFSwitchConfig)) {
-            return false;
-        }
-        OFSwitchConfig other = (OFSwitchConfig) obj;
-        if (flags != other.flags) {
-            return false;
-        }
-        if (missSendLength != other.missSendLength) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFType.java b/src/main/java/org/openflow/protocol/OFType.java
deleted file mode 100644
index f1c81e288..000000000
--- a/src/main/java/org/openflow/protocol/OFType.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.lang.reflect.Constructor;
-
-/**
- * List of OpenFlow types and mappings to wire protocol value and derived
- * classes
- *
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- * @author David Erickson (daviderickson@cs.stanford.edu)
- *
- */
-public enum OFType {
-    HELLO               (0, OFHello.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFHello();
-                            }}),
-    ERROR               (1, OFError.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFError();
-                            }}),
-    ECHO_REQUEST        (2, OFEchoRequest.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFEchoRequest();
-                            }}),
-    ECHO_REPLY          (3, OFEchoReply.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFEchoReply();
-                            }}),
-    VENDOR              (4, OFVendor.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFVendor();
-                            }}),
-    FEATURES_REQUEST    (5, OFFeaturesRequest.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFFeaturesRequest();
-                            }}),
-    FEATURES_REPLY      (6, OFFeaturesReply.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFFeaturesReply();
-                            }}),
-    GET_CONFIG_REQUEST  (7, OFGetConfigRequest.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFGetConfigRequest();
-                            }}),
-    GET_CONFIG_REPLY    (8, OFGetConfigReply.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFGetConfigReply();
-                            }}),
-    SET_CONFIG          (9, OFSetConfig.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFSetConfig();
-                            }}),
-    PACKET_IN           (10, OFPacketIn.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFPacketIn();
-                            }}),
-    FLOW_REMOVED        (11, OFFlowRemoved.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFFlowRemoved();
-                            }}),
-    PORT_STATUS         (12, OFPortStatus.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFPortStatus();
-                            }}),
-    PACKET_OUT          (13, OFPacketOut.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFPacketOut();
-                            }}),
-    FLOW_MOD            (14, OFFlowMod.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFFlowMod();
-                            }}),
-    PORT_MOD            (15, OFPortMod.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFPortMod();
-                            }}),
-    STATS_REQUEST       (16, OFStatisticsRequest.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFStatisticsRequest();
-                            }}),
-    STATS_REPLY         (17, OFStatisticsReply.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFStatisticsReply();
-                            }}),
-    BARRIER_REQUEST     (18, OFBarrierRequest.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFBarrierRequest();
-                            }}),
-    BARRIER_REPLY       (19, OFBarrierReply.class, new Instantiable<OFMessage>() {
-                            @Override
-                            public OFMessage instantiate() {
-                                return new OFBarrierReply();
-                            }}),
-    QUEUE_GET_CONFIG_REQUEST    (20, OFQueueGetConfigRequest.class, new Instantiable<OFMessage>() {
-                                    @Override
-                                    public OFMessage instantiate() {
-                                        return new OFQueueGetConfigRequest();
-                                    }}),
-    QUEUE_GET_CONFIG_REPLY      (21, OFQueueGetConfigReply.class, new Instantiable<OFMessage>() {
-                                    @Override
-                                    public OFMessage instantiate() {
-                                        return new OFQueueGetConfigReply();
-                                    }});
-
-    static OFType[] mapping;
-
-    protected Class<? extends OFMessage> clazz;
-    protected Constructor<? extends OFMessage> constructor;
-    protected Instantiable<OFMessage> instantiable;
-    protected byte type;
-
-    /**
-     * Store some information about the OpenFlow type, including wire protocol
-     * type number, length, and derived class
-     *
-     * @param type Wire protocol number associated with this OFType
-     * @param clazz The Java class corresponding to this type of OpenFlow
-     *              message
-     * @param instantiator An Instantiator<OFMessage> implementation that creates an
-     *          instance of the specified OFMessage
-     */
-    OFType(int type, Class<? extends OFMessage> clazz, Instantiable<OFMessage> instantiator) {
-        this.type = (byte) type;
-        this.clazz = clazz;
-        this.instantiable = instantiator;
-        try {
-            this.constructor = clazz.getConstructor(new Class[]{});
-        } catch (Exception e) {
-            throw new RuntimeException(
-                    "Failure getting constructor for class: " + clazz, e);
-        }
-        OFType.addMapping(this.type, this);
-    }
-
-    /**
-     * Adds a mapping from type value to OFType enum
-     *
-     * @param i OpenFlow wire protocol type
-     * @param t type
-     */
-    static public void addMapping(byte i, OFType t) {
-        if (mapping == null)
-            mapping = new OFType[32];
-        OFType.mapping[i] = t;
-    }
-
-    /**
-     * Remove a mapping from type value to OFType enum
-     *
-     * @param i OpenFlow wire protocol type
-     */
-    static public void removeMapping(byte i) {
-        OFType.mapping[i] = null;
-    }
-
-    /**
-     * Given a wire protocol OpenFlow type number, return the OFType associated
-     * with it
-     *
-     * @param i wire protocol number
-     * @return OFType enum type
-     */
-
-    static public OFType valueOf(Byte i) {
-        return OFType.mapping[i];
-    }
-
-    /**
-     * @return Returns the wire protocol value corresponding to this OFType
-     */
-    public byte getTypeValue() {
-        return this.type;
-    }
-
-    /**
-     * @return return the OFMessage subclass corresponding to this OFType
-     */
-    public Class<? extends OFMessage> toClass() {
-        return clazz;
-    }
-
-    /**
-     * Returns the no-argument Constructor of the implementation class for
-     * this OFType
-     * @return the constructor
-     */
-    public Constructor<? extends OFMessage> getConstructor() {
-        return constructor;
-    }
-
-    /**
-     * Returns a new instance of the OFMessage represented by this OFType
-     * @return the new object
-     */
-    public OFMessage newInstance() {
-        return instantiable.instantiate();
-    }
-
-    /**
-     * @return the instantiable
-     */
-    public Instantiable<OFMessage> getInstantiable() {
-        return instantiable;
-    }
-
-    /**
-     * @param instantiable the instantiable to set
-     */
-    public void setInstantiable(Instantiable<OFMessage> instantiable) {
-        this.instantiable = instantiable;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/OFVendor.java b/src/main/java/org/openflow/protocol/OFVendor.java
deleted file mode 100644
index 8ecb862be..000000000
--- a/src/main/java/org/openflow/protocol/OFVendor.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-import org.openflow.protocol.factory.OFVendorDataFactory;
-import org.openflow.protocol.factory.OFVendorDataFactoryAware;
-import org.openflow.protocol.vendor.OFVendorData;
-
-/**
- * Represents ofp_vendor_header
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFVendor extends OFMessage implements OFVendorDataFactoryAware {
-    public static int MINIMUM_LENGTH = 12;
-
-    protected int vendor;
-    protected OFVendorData vendorData;
-    protected OFVendorDataFactory vendorDataFactory;
-
-    public OFVendor() {
-        super();
-        this.type = OFType.VENDOR;
-        this.length = U16.t(MINIMUM_LENGTH);
-    }
-
-    /**
-     * @return the vendor
-     */
-    public int getVendor() {
-        return vendor;
-    }
-
-    /**
-     * @param vendor the vendor to set
-     */
-    public void setVendor(int vendor) {
-        this.vendor = vendor;
-    }
-
-    /**
-     * @return the data
-     */
-    public OFVendorData getVendorData() {
-        return vendorData;
-    }
-
-    /**
-     * @param data the data to set
-     */
-    public void setVendorData(OFVendorData vendorData) {
-        this.vendorData = vendorData;
-    }
-
-    @Override
-    public void setVendorDataFactory(OFVendorDataFactory vendorDataFactory) {
-        this.vendorDataFactory = vendorDataFactory;
-    }
-      
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.vendor = data.readInt();
-        if (vendorDataFactory == null)
-            throw new RuntimeException("OFVendorDataFactory not set");
-            
-        this.vendorData = vendorDataFactory.parseVendorData(vendor,
-                data, super.getLengthU() - MINIMUM_LENGTH);
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeInt(this.vendor);
-        if (vendorData != null)
-            vendorData.writeTo(data);
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#hashCode()
-     */
-    @Override
-    public int hashCode() {
-        final int prime = 337;
-        int result = super.hashCode();
-        result = prime * result + vendor;
-        if (vendorData != null)
-            result = prime * result + vendorData.hashCode();
-        return result;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#equals(java.lang.Object)
-     */
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (!super.equals(obj))
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        OFVendor other = (OFVendor) obj;
-        if (vendor != other.vendor)
-            return false;
-        if (vendorData == null) {
-            if (other.vendorData != null) {
-                return false;
-            }
-        } else if (!vendorData.equals(other.vendorData)) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/Wildcards.java b/src/main/java/org/openflow/protocol/Wildcards.java
deleted file mode 100644
index 4b0ea07b5..000000000
--- a/src/main/java/org/openflow/protocol/Wildcards.java
+++ /dev/null
@@ -1,603 +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 org.openflow.protocol;
-
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.List;
-
-import com.google.common.base.Joiner;
-
-/**
- * a more user friendly representation of the wildcards bits in an OpenFlow
- * match. The Wildcards object is
- * <ul>
- * <li>immutable (i.e., threadsafe)</li>
- * <li>instance managed (don't instantiate it yourself), instead call "of"</li>
- * <ul>
- * <p>
- * You can construct a Wildcard object from either its integer representation
- * </p>
- * <code>
- *    Wildcard.of(0x3820e0);
- *  </code>
- * <p>
- * Or start with either an empty or full wildcard, and select/unselect foo.
- * </p>
- * <code>
- *  Wildcard w = Wildcards.NONE
- *                .set(Flag.DL_SRC, Flag. DL_DST, Flag.DL_VLAN_PCP)
- *                .setNwDstMask(8)
- *                .setNwSrcMask(8);
- *  </code>
- * <p>
- * <b>Remember:</b> Wildcards objects are immutable. set... operations have
- * <b>NO EFFECT</b> on the current wildcard object. You HAVE to use the returned
- * changed object.
- * </p>
- *
- * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
- */
-public class Wildcards {
-
-    public final static Wildcards FULL = new Wildcards(OFMatch.OFPFW_ALL_SANITIZED);
-    private static final int FULL_INT = FULL.getInt();
-
-    public final static Wildcards EXACT = new Wildcards(0);
-
-    // floodlight common case: matches on inport + l2
-    public final static int INT_INPORT_L2_MATCH = 0x3820e0;
-    public final static Wildcards INPORT_L2_MATCH = new Wildcards(
-            INT_INPORT_L2_MATCH);
-
-    /**
-     * enum type for the binary flags that can be set in the wildcards field of
-     * an OFMatch. Replaces the unwieldy c-ish int constants in OFMatch.
-     */
-    public static enum Flag {
-        IN_PORT(OFMatch.OFPFW_IN_PORT),  /* Switch input port. */
-        DL_VLAN(OFMatch.OFPFW_DL_VLAN), /* VLAN id. */
-        DL_SRC(OFMatch.OFPFW_DL_SRC), /* Ethernet source address. */
-        DL_DST(OFMatch.OFPFW_DL_DST), /* Ethernet destination addr */
-        DL_TYPE(OFMatch.OFPFW_DL_TYPE), /* Ethernet frame type. */
-        NW_PROTO(OFMatch.OFPFW_NW_PROTO), /* IP protocol. */
-        TP_SRC(OFMatch.OFPFW_TP_SRC), /* TCP/UDP source port. */
-        TP_DST(OFMatch.OFPFW_TP_DST), /* TCP/UDP destination port. */
-        DL_VLAN_PCP(OFMatch.OFPFW_DL_VLAN_PCP), /* VLAN priority. */
-        NW_SRC(-1) { /*
-                      * virtual NW_SRC flag => translates to the strange 6 bits
-                      * in the header
-                      */
-            @Override
-            boolean isBolean() {
-                return false;
-            }
-
-            @Override
-            int getInt(int flags) {
-                return ((flags & OFMatch.OFPFW_NW_SRC_MASK) >> OFMatch.OFPFW_NW_SRC_SHIFT);
-            }
-
-            @Override
-            int setInt(int flags, int srcMask) {
-                return (flags & ~OFMatch.OFPFW_NW_SRC_MASK) | (srcMask << OFMatch.OFPFW_NW_SRC_SHIFT);
-            }
-
-            @Override
-            int wildcard(int flags) {
-                return flags & ~OFMatch.OFPFW_NW_SRC_MASK;
-            }
-
-            @Override
-            int matchOn(int flags) {
-                return flags | OFMatch.OFPFW_NW_SRC_ALL;
-            }
-
-            @Override
-            boolean isPartiallyOn(int flags) {
-                int intValue = getInt(flags);
-                return intValue > 0 && intValue < 32;
-            }
-
-            @Override
-            boolean isFullyOn(int flags) {
-                return getInt(flags) >= 32;
-            }
-
-        },
-        NW_DST(-1) { /*
-                      * virtual NW_SRC flag => translates to the strange 6 bits
-                      * in the header
-                      */
-            @Override
-            boolean isBolean() {
-                return false;
-            }
-
-            @Override
-            int getInt(int flags) {
-                return ((flags & OFMatch.OFPFW_NW_DST_MASK) >> OFMatch.OFPFW_NW_DST_SHIFT);
-            }
-
-            @Override
-            int setInt(int flags, int srcMask) {
-                return (flags & ~OFMatch.OFPFW_NW_DST_MASK) | (srcMask << OFMatch.OFPFW_NW_DST_SHIFT);
-            }
-
-            @Override
-            int wildcard(int flags) {
-                return flags & ~OFMatch.OFPFW_NW_DST_MASK;
-            }
-
-            @Override
-            int matchOn(int flags) {
-                return flags | OFMatch.OFPFW_NW_DST_ALL;
-            }
-
-            @Override
-            boolean isFullyOn(int flags) {
-                return getInt(flags) >= 32;
-            }
-        },
-        NW_TOS(OFMatch.OFPFW_NW_TOS); /* IP ToS (DSCP field, 6 bits). */
-
-        final int bitPosition;
-
-        Flag(int bitPosition) {
-            this.bitPosition = bitPosition;
-        }
-
-        /**
-         * @return a modified OF-1.0 flags field with this flag cleared (match
-         *         on this field)
-         */
-        int matchOn(int flags) {
-            return flags & ~this.bitPosition;
-        }
-
-        /**
-         * @return a modified OF-1.0 flags field with this flag set (wildcard
-         *         this field)
-         */
-        int wildcard(int flags) {
-            return flags | this.bitPosition;
-        }
-
-        /**
-         * @return true iff this is a true boolean flag that can either be off
-         *         or on.True in OF-1.0 for all fields except NW_SRC and NW_DST
-         */
-        boolean isBolean() {
-            return false;
-        }
-
-        /**
-         * @return true iff this wildcard field is currently 'partially on'.
-         *         Always false for true Boolean Flags. Can be true in OF-1.0
-         *         for NW_SRC, NW_DST.
-         */
-        boolean isPartiallyOn(int flags) {
-            return false;
-        }
-
-        /**
-         * @return true iff this wildcard field currently fully on (fully
-         *         wildcarded). Equivalent to the boolean flag being set in the
-         *         bitmask for bit flags, and to the wildcarded bit length set
-         *         to >=32 for NW_SRC and NW_DST
-         * @param flags
-         * @return
-         */
-        boolean isFullyOn(int flags) {
-            return (flags & this.bitPosition) != 0;
-        }
-
-        /**
-         * set the integer representation of this flag. only for NW_SRC and
-         * NW_DST
-         */
-        int setInt(int flags, int srcMask) {
-            throw new UnsupportedOperationException();
-        }
-
-        /**
-         * set the integer representation of this flag. only for NW_SRC and
-         * NW_DST
-         */
-        int getInt(int flags) {
-            throw new UnsupportedOperationException();
-        }
-
-
-    }
-
-    private final int flags;
-
-    /** private constructor. use Wildcard.of() instead */
-    private Wildcards(int flags) {
-        this.flags = flags;
-    }
-
-    /**
-     * return a wildcard object matching the given int flags. May reuse / cache
-     * frequently used wildcard instances. Don't rely on it though (use equals
-     * not ==).
-     *
-     * @param flags
-     * @return
-     */
-    public static Wildcards of(int paramFlags) {
-        int flags = sanitizeInt(paramFlags);
-        switch(flags) {
-            case 0x0000:
-                return EXACT;
-            case OFMatch.OFPFW_ALL_SANITIZED:
-                return FULL;
-            case INT_INPORT_L2_MATCH:
-                return INPORT_L2_MATCH;
-            default:
-                return new Wildcards(flags);
-        }
-    }
-
-    /** convience method return a wildcard for exactly one set flag */
-    public static Wildcards of(Wildcards.Flag setFlag) {
-        return Wildcards.of(setFlag.wildcard(0));
-    }
-
-    /** convience method return a wildcard for exactly two set flags */
-    public static Wildcards of(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
-        return Wildcards.of(setFlag.wildcard(setFlag2.wildcard(0)));
-    }
-
-    /** convience method return a wildcard for an arbitrary number of set flags */
-    public static Wildcards of(Wildcards.Flag... setFlags) {
-        int flags = 0;
-        for (Wildcards.Flag flag : setFlags)
-            flags = flag.wildcard(0);
-        return Wildcards.of(flags);
-    }
-
-    /** convience method return a wildcards for ofmatches that match on one flag */
-    public static Wildcards ofMatches(Wildcards.Flag setFlag) {
-        return Wildcards.of(setFlag.matchOn(FULL_INT));
-    }
-
-    /**
-     * convience method return a wildcard for for an ofmatch that match on two
-     * flags
-     */
-    public static Wildcards ofMatches(Wildcards.Flag setFlag, Wildcards.Flag setFlag2) {
-        return Wildcards.of(setFlag.matchOn(setFlag2.matchOn(FULL_INT)));
-    }
-
-    /**
-     * convience method return a wildcard for an ofmatch that amtch on an
-     * arbitrary number of set flags
-     */
-    public static Wildcards ofMatches(Wildcards.Flag... setFlags) {
-        int flags = FULL_INT;
-        for (Wildcards.Flag flag : setFlags)
-           flags = flag.matchOn(flags);
-        return Wildcards.of(flags);
-    }
-
-    /**
-     * return a Wildcards object that has the given flags set
-     * <p>
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     */
-    public Wildcards wildcard(Wildcards.Flag flag) {
-        int flags = flag.wildcard(this.flags);
-        if (flags == this.flags)
-            return this;
-        else
-            return new Wildcards(flags);
-    }
-
-    /**
-     * return a Wildcards object that has the given flags set
-     * <p>
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     */
-    public Wildcards wildcard(Wildcards.Flag flag, Wildcards.Flag flag2) {
-        int flags = flag.wildcard(flag2.wildcard(this.flags));
-        if (flags == this.flags)
-            return this;
-        else
-            return new Wildcards(flags);
-    }
-
-    /**
-     * return a Wildcards object that has the given flags wildcarded
-     * <p>
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     */
-    public Wildcards wildcard(Wildcards.Flag... setFlags) {
-        int flags = this.flags;
-        for (Wildcards.Flag flag : setFlags)
-            flags = flag.wildcard(flags);
-        if (flags == this.flags)
-            return this;
-        else
-            return new Wildcards(flags);
-    }
-
-    /**
-     * return a Wildcards object that matches on exactly the given flag
-     * <p>
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     */
-    public Wildcards matchOn(Wildcards.Flag flag) {
-        int flags = flag.matchOn(this.flags);
-        if (flags == this.flags)
-            return this;
-        else
-            return new Wildcards(flags);
-    }
-
-    /**
-     * return a Wildcards object that matches on exactly the given flags
-     * <p>
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     */
-    public Wildcards matchOn(Wildcards.Flag flag, Wildcards.Flag flag2) {
-        int flags = flag.matchOn(flag2.matchOn(this.flags));
-        if (flags == this.flags)
-            return this;
-        else
-            return new Wildcards(flags);
-    }
-
-    /**
-     * return a Wildcards object that matches on exactly the given flags
-     * <p>
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     */
-    public Wildcards matchOn(Wildcards.Flag... setFlags) {
-        int flags = this.flags;
-        for (Wildcards.Flag flag : setFlags)
-            flags = flag.matchOn(flags);
-        if (flags == this.flags)
-            return this;
-        else
-            return new Wildcards(flags);
-    }
-
-    /**
-     * return the nw src mask in normal CIDR style, e.g., 8 means x.x.x.x/8
-     * means 8 bits wildcarded
-     */
-    public int getNwSrcMask() {
-        return Math.max(0, 32 - Flag.NW_SRC.getInt(flags));
-    }
-
-    /**
-     * return the nw dst mask in normal CIDR style, e.g., 8 means x.x.x.x/8
-     * means 8 bits wildcarded
-     */
-    public int getNwDstMask() {
-        return Math.max(0, 32 - Flag.NW_DST.getInt(flags));
-    }
-
-    /**
-     * return a Wildcard object that has the given nwSrcCidrMask set.
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     *
-     * @param srcCidrMask
-     *            source mask to set in <b>normal CIDR notation</b>, i.e., 8
-     *            means x.x.x.x/8
-     * @return a modified object
-     */
-    public Wildcards withNwSrcMask(int srcCidrMask) {
-        int flags = Flag.NW_SRC.setInt(this.flags, Math.max(0, 32 - srcCidrMask));
-        if (flags == this.flags)
-            return this;
-        else
-            return new Wildcards(flags);
-    }
-
-    /**
-     * return a Wildcard object that has the given nwDstCidrMask set.
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     *
-     * @param dstCidrMask
-     *            dest mask to set in <b>normal CIDR notation</b>, i.e., 8 means
-     *            x.x.x.x/8
-     * @return a modified object
-     */
-    public Wildcards withNwDstMask(int dstCidrMask) {
-        int flags = Flag.NW_DST.setInt(this.flags, Math.max(0, 32 - dstCidrMask));
-        if (flags == this.flags)
-            return this;
-        else
-            return new Wildcards(flags);
-    }
-
-    /**
-     * return a Wildcard object that is inverted to this wildcard object.
-     * <b>NOTE:</b> NOT a mutator function. 'this' wildcard object stays
-     * unmodified. </b>
-     * @return a modified object
-     */
-    public Wildcards inverted() {
-        return Wildcards.of(flags ^ OFMatch.OFPFW_ALL_SANITIZED);
-    }
-
-    public boolean isWildcarded(Flag flag) {
-        return flag.isFullyOn(flags);
-    }
-
-    /**
-     * return all wildcard flags that are fully wildcarded as an EnumSet. Do not
-     * modify. Note: some flags (like NW_SRC and NW_DST) that are partially
-     * wildcarded are not returned in this set.
-     *
-     * @return the EnumSet of wildcards
-     */
-    public EnumSet<Wildcards.Flag> getWildcardedFlags() {
-        EnumSet<Wildcards.Flag> res = EnumSet.noneOf(Wildcards.Flag.class);
-        for (Wildcards.Flag flag : Flag.values()) {
-            if (flag.isFullyOn(flags)) {
-                res.add(flag);
-            }
-        }
-        return res;
-    }
-
-    /** return the OpenFlow 'wire' integer representation of these wildcards */
-    public int getInt() {
-        return flags;
-    }
-
-    /**
-     * return the OpenFlow 'wire' integer representation of these wildcards.
-     * Sanitize nw_src and nw_dst to be max. 32 (values > 32 are technically
-     * possible, but don't make semantic sense)
-     */
-    public static int sanitizeInt(int flags) {
-        if (((flags & OFMatch.OFPFW_NW_SRC_MASK) >> OFMatch.OFPFW_NW_SRC_SHIFT) > 32) {
-            flags = (flags & ~OFMatch.OFPFW_NW_SRC_MASK) | OFMatch.OFPFW_NW_SRC_ALL;
-        }
-        if (((flags & OFMatch.OFPFW_NW_DST_MASK) >> OFMatch.OFPFW_NW_DST_SHIFT) > 32) {
-            flags = (flags & ~OFMatch.OFPFW_NW_DST_MASK) | OFMatch.OFPFW_NW_DST_ALL;
-        }
-        return flags;
-    }
-
-    /**
-     * is this a wildcard set that has all flags set + and full (/0) nw_src and
-     * nw_dst wildcarding ?
-     */
-    public boolean isFull() {
-        return flags == OFMatch.OFPFW_ALL || flags == OFMatch.OFPFW_ALL_SANITIZED;
-    }
-
-    /** is this a wildcard of an exact match */
-    public boolean isExact() {
-        return flags == 0;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + flags;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        Wildcards other = (Wildcards) obj;
-        if (flags != other.flags)
-            return false;
-        return true;
-    }
-
-    private final static Joiner pipeJoiner = Joiner.on("|");
-
-    @Override
-    public String toString() {
-        List<String> res = new ArrayList<String>();
-        for (Wildcards.Flag flag : Flag.values()) {
-            if (flag.isFullyOn(flags)) {
-                res.add(flag.name().toLowerCase());
-            }
-        }
-
-        if (Flag.NW_SRC.isPartiallyOn(flags)) {
-            res.add("nw_src(/" + getNwSrcMask() + ")");
-        }
-
-        if (Flag.NW_DST.isPartiallyOn(flags)) {
-            res.add("nw_dst(/" + getNwDstMask() + ")");
-        }
-
-        return pipeJoiner.join(res);
-    }
-
-    private final static Joiner commaJoiner = Joiner.on(", ");
-
-    /** a Java expression that constructs 'this' wildcards set */
-    public String toJava() {
-        if(isFull()) {
-            return "Wildcards.FULL";
-        } else  if (isExact()){
-            return "Wildcards.EXACT";
-        }
-
-        StringBuilder b = new StringBuilder();
-
-        EnumSet<Flag> myFlags = getWildcardedFlags();
-        if (myFlags.size() < 3) {
-            // default to start with empty
-            b.append("Wildcards.of("
-                     + commaJoiner.join(prefix("Flag.", myFlags.iterator())) + ")");
-        } else {
-            // too many - start with full
-
-            EnumSet<Flag> invFlags = inverted().getWildcardedFlags();
-            b.append("Wildcards.ofMatches("
-                     + commaJoiner.join(prefix("Flag.", invFlags.iterator())) + ")");
-        }
-        if (Flag.NW_SRC.isPartiallyOn(flags)) {
-            b.append(".setNwSrcMask(" + getNwSrcMask() + ")");
-        }
-        if (Flag.NW_DST.isPartiallyOn(flags)) {
-            b.append(".setNwDstMask(" + getNwDstMask() + ")");
-        }
-        return b.toString();
-    }
-
-    private Iterator<String> prefix(final String prefix, final Iterator<?> i) {
-        return new Iterator<String>() {
-
-            @Override
-            public boolean hasNext() {
-                return i.hasNext();
-            }
-
-            @Override
-            public String next() {
-                Object next = i.next();
-                return next == null ? null : prefix + next.toString();
-            }
-
-            @Override
-            public void remove() {
-                i.remove();
-            }
-        };
-    }
-
-
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFAction.java b/src/main/java/org/openflow/protocol/action/OFAction.java
deleted file mode 100644
index 57b5dc1ef..000000000
--- a/src/main/java/org/openflow/protocol/action/OFAction.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.action;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.U16;
-
-/**
- * The base class for all OpenFlow Actions.
- *
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public class OFAction implements Cloneable {
-    /**
-     * Note the true minimum length for this header is 8 including a pad to 64
-     * bit alignment, however as this base class is used for demuxing an
-     * incoming Action, it is only necessary to read the first 4 bytes.  All
-     * Actions extending this class are responsible for reading/writing the
-     * first 8 bytes, including the pad if necessary.
-     */
-    public static int MINIMUM_LENGTH = 4;
-    public static int OFFSET_LENGTH = 2;
-    public static int OFFSET_TYPE = 0;
-
-    protected OFActionType type;
-    protected short length;
-
-    /**
-     * Get the length of this message
-     *
-     * @return
-     */
-    public short getLength() {
-        return length;
-    }
-
-    /**
-     * Get the length of this message, unsigned
-     *
-     * @return
-     */
-    public int getLengthU() {
-        return U16.f(length);
-    }
-
-    /**
-     * Set the length of this message
-     *
-     * @param length
-     */
-    public OFAction setLength(short length) {
-        this.length = length;
-        return this;
-    }
-
-    /**
-     * Get the type of this message
-     *
-     * @return OFActionType enum
-     */
-    public OFActionType getType() {
-        return this.type;
-    }
-
-    /**
-     * Set the type of this message
-     *
-     * @param type
-     */
-    public void setType(OFActionType type) {
-        this.type = type;
-    }
-
-    /**
-     * Returns a summary of the message
-     * @return "ofmsg=v=$version;t=$type:l=$len:xid=$xid"
-     */
-    public String toString() {
-        return "ofaction" +
-            ";t=" + this.getType() +
-            ";l=" + this.getLength();
-    }
-    
-    /**
-     * Given the output from toString(), 
-     * create a new OFAction
-     * @param val
-     * @return
-     */
-    public static OFAction fromString(String val) {
-        String tokens[] = val.split(";");
-        if (!tokens[0].equals("ofaction"))
-            throw new IllegalArgumentException("expected 'ofaction' but got '" + 
-                    tokens[0] + "'");
-        String type_tokens[] = tokens[1].split("="); 
-        String len_tokens[] = tokens[2].split("=");
-        OFAction action = new OFAction();
-        action.setLength(Short.valueOf(len_tokens[1]));
-        action.setType(OFActionType.valueOf(type_tokens[1]));
-        return action;
-    }
-
-    public void readFrom(ChannelBuffer data) {
-        this.type = OFActionType.valueOf(data.readShort());
-        this.length = data.readShort();
-        // Note missing PAD, see MINIMUM_LENGTH comment for details
-    }
-
-    public void writeTo(ChannelBuffer data) {
-        data.writeShort(type.getTypeValue());
-        data.writeShort(length);
-        // Note missing PAD, see MINIMUM_LENGTH comment for details
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 347;
-        int result = 1;
-        result = prime * result + length;
-        result = prime * result + ((type == null) ? 0 : type.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFAction)) {
-            return false;
-        }
-        OFAction other = (OFAction) obj;
-        if (length != other.length) {
-            return false;
-        }
-        if (type == null) {
-            if (other.type != null) {
-                return false;
-            }
-        } else if (!type.equals(other.type)) {
-            return false;
-        }
-        return true;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#clone()
-     */
-    @Override
-    public OFAction clone() throws CloneNotSupportedException {
-        return (OFAction) super.clone();
-    }
-    
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java b/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java
deleted file mode 100644
index 644dc5f2f..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-import java.util.Arrays;
-
-import net.floodlightcontroller.core.web.serializers.ByteArrayMACSerializer;
-import net.floodlightcontroller.util.MACAddress;
-
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.OFPhysicalPort;
-
-/**
- * Represents an ofp_action_dl_addr
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public abstract class OFActionDataLayer extends OFAction {
-    public static int MINIMUM_LENGTH = 16;
-
-    protected byte[] dataLayerAddress;
-
-    /**
-     * @return the dataLayerAddress
-     */
-    @JsonSerialize(using=ByteArrayMACSerializer.class)
-    public byte[] getDataLayerAddress() {
-        return dataLayerAddress;
-    }
-
-    /**
-     * @param dataLayerAddress the dataLayerAddress to set
-     */
-    public void setDataLayerAddress(byte[] dataLayerAddress) {
-        this.dataLayerAddress = dataLayerAddress;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        if (this.dataLayerAddress == null)
-            this.dataLayerAddress = new byte[OFPhysicalPort.OFP_ETH_ALEN];
-        data.readBytes(this.dataLayerAddress);
-        data.readInt();
-        data.readShort();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeBytes(this.dataLayerAddress);
-        data.writeInt(0);
-        data.writeShort((short) 0);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 347;
-        int result = super.hashCode();
-        result = prime * result + Arrays.hashCode(dataLayerAddress);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionDataLayer)) {
-            return false;
-        }
-        OFActionDataLayer other = (OFActionDataLayer) obj;
-        if (!Arrays.equals(dataLayerAddress, other.dataLayerAddress)) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(type);
-        builder.append("[");
-        builder.append(MACAddress.valueOf(dataLayerAddress).toString());
-        builder.append("]");
-        return builder.toString();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java b/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java
deleted file mode 100644
index 48b8d0f84..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.action;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFActionDataLayerDestination extends OFActionDataLayer {
-    public OFActionDataLayerDestination() {
-        super();
-        super.setType(OFActionType.SET_DL_DST);
-        super.setLength((short) OFActionDataLayer.MINIMUM_LENGTH);
-    }
-    
-    public OFActionDataLayerDestination(byte[] address) {
-        this();
-        this.dataLayerAddress = address;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java b/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java
deleted file mode 100644
index e04561cee..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.action;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFActionDataLayerSource extends OFActionDataLayer {
-    public OFActionDataLayerSource() {
-        super();
-        super.setType(OFActionType.SET_DL_SRC);
-        super.setLength((short) OFActionDataLayer.MINIMUM_LENGTH);
-    }
-    
-    public OFActionDataLayerSource(byte[] address) {
-        this();
-        this.dataLayerAddress = address;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java b/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java
deleted file mode 100644
index 537716612..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_action_enqueue
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public class OFActionEnqueue extends OFAction {
-    public static int MINIMUM_LENGTH = 16;
-
-    protected short port;
-    protected int queueId;
-
-    public OFActionEnqueue() {
-        super.setType(OFActionType.OPAQUE_ENQUEUE);
-        super.setLength((short) MINIMUM_LENGTH);
-    }
-    
-    public OFActionEnqueue(short port, int queueId) {
-        this();
-        this.port = port;
-        this.queueId = queueId;
-    }
-
-    /**
-     * Get the output port
-     * @return
-     */
-    public short getPort() {
-        return this.port;
-    }
-
-    /**
-     * Set the output port
-     * @param port
-     */
-    public void setPort(short port) {
-        this.port = port;
-    }
-
-    /**
-     * @return the queueId
-     */
-    public int getQueueId() {
-        return queueId;
-    }
-
-    /**
-     * @param queueId the queueId to set
-     */
-    public void setQueueId(int queueId) {
-        this.queueId = queueId;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.port = data.readShort();
-        data.readShort();
-        data.readInt();
-        this.queueId = data.readInt();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.port);
-        data.writeShort((short) 0);
-        data.writeInt(0);
-        data.writeInt(this.queueId);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 349;
-        int result = super.hashCode();
-        result = prime * result + port;
-        result = prime * result + queueId;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionEnqueue)) {
-            return false;
-        }
-        OFActionEnqueue other = (OFActionEnqueue) obj;
-        if (port != other.port) {
-            return false;
-        }
-        if (queueId != other.queueId) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(type);
-        builder.append("[");
-        builder.append("Port: ");
-        builder.append(port);
-        builder.append(", Queue Id: ");
-        builder.append(queueId);
-        builder.append("]");
-        return builder.toString();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java b/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java
deleted file mode 100644
index 67bc5a822..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-
-import net.floodlightcontroller.packet.IPv4;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_action_nw_addr
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public abstract class OFActionNetworkLayerAddress extends OFAction {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected int networkAddress;
-
-    /**
-     * @return the networkAddress
-     */
-    public int getNetworkAddress() {
-        return networkAddress;
-    }
-
-    /**
-     * @param networkAddress the networkAddress to set
-     */
-    public void setNetworkAddress(int networkAddress) {
-        this.networkAddress = networkAddress;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.networkAddress = data.readInt();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeInt(this.networkAddress);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 353;
-        int result = super.hashCode();
-        result = prime * result + networkAddress;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionNetworkLayerAddress)) {
-            return false;
-        }
-        OFActionNetworkLayerAddress other = (OFActionNetworkLayerAddress) obj;
-        if (networkAddress != other.networkAddress) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(type);
-        builder.append("[");
-        builder.append(IPv4.fromIPv4Address(networkAddress));
-        builder.append("]");
-        return builder.toString();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java b/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java
deleted file mode 100644
index 13c14ff0b..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.action;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFActionNetworkLayerDestination extends OFActionNetworkLayerAddress {
-    public OFActionNetworkLayerDestination() {
-        super();
-        super.setType(OFActionType.SET_NW_DST);
-        super.setLength((short) OFActionNetworkLayerAddress.MINIMUM_LENGTH);
-    }
-    
-    public OFActionNetworkLayerDestination(int ip) {
-        this();
-        this.networkAddress = ip;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java b/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java
deleted file mode 100644
index ef1d005e3..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.action;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFActionNetworkLayerSource extends OFActionNetworkLayerAddress {
-    public OFActionNetworkLayerSource() {
-        super();
-        super.setType(OFActionType.SET_NW_SRC);
-        super.setLength((short) OFActionNetworkLayerAddress.MINIMUM_LENGTH);
-    }
-    
-    public OFActionNetworkLayerSource(int ip) {
-        this();
-        this.networkAddress = ip;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java b/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java
deleted file mode 100644
index ec91c7649..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_action_enqueue
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public class OFActionNetworkTypeOfService extends OFAction {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected byte networkTypeOfService;
-
-    public OFActionNetworkTypeOfService() {
-        super.setType(OFActionType.SET_NW_TOS);
-        super.setLength((short) MINIMUM_LENGTH);
-    }
-    
-    public OFActionNetworkTypeOfService(byte tos) {
-        this();
-        this.networkTypeOfService = tos;
-    }
-    
-
-    /**
-     * @return the networkTypeOfService
-     */
-    public byte getNetworkTypeOfService() {
-        return networkTypeOfService;
-    }
-
-    /**
-     * @param networkTypeOfService the networkTypeOfService to set
-     */
-    public void setNetworkTypeOfService(byte networkTypeOfService) {
-        this.networkTypeOfService = networkTypeOfService;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.networkTypeOfService = data.readByte();
-        data.readShort();
-        data.readByte();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeByte(this.networkTypeOfService);
-        data.writeShort((short) 0);
-        data.writeByte((byte) 0);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 359;
-        int result = super.hashCode();
-        result = prime * result + networkTypeOfService;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionNetworkTypeOfService)) {
-            return false;
-        }
-        OFActionNetworkTypeOfService other = (OFActionNetworkTypeOfService) obj;
-        if (networkTypeOfService != other.networkTypeOfService) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(type);
-        builder.append("[");
-        builder.append(networkTypeOfService);
-        builder.append("]");
-        return builder.toString();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFActionOutput.java b/src/main/java/org/openflow/protocol/action/OFActionOutput.java
deleted file mode 100644
index beca7e4f2..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionOutput.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- */
-public class OFActionOutput extends OFAction implements Cloneable {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected short port;
-    protected short maxLength;
-
-    public OFActionOutput() {
-        super.setType(OFActionType.OUTPUT);
-        super.setLength((short) MINIMUM_LENGTH);
-    }
-
-    /**
-     * Create an Output Action sending packets out the specified
-     * OpenFlow port.
-     *
-     * This is the most common creation pattern for OFActions.
-     *
-     * @param port
-     */
-
-    public OFActionOutput(short port) {
-        this(port, (short) 65535);
-    }
-
-    /**
-     * Create an Output Action specifying both the port AND
-     * the snaplen of the packet to send out that port.
-     * The length field is only meaningful when port == OFPort.OFPP_CONTROLLER
-     * @param port
-     * @param maxLength The maximum number of bytes of the packet to send.
-     * Most hardware only supports this value for OFPP_CONTROLLER
-     */
-
-    public OFActionOutput(short port, short maxLength) {
-        super();
-        super.setType(OFActionType.OUTPUT);
-        super.setLength((short) MINIMUM_LENGTH);
-        this.port = port;
-        this.maxLength = maxLength;
-    }
-
-    /**
-     * Get the output port
-     * @return
-     */
-    public short getPort() {
-        return this.port;
-    }
-
-    /**
-     * Set the output port
-     * @param port
-     */
-    public OFActionOutput setPort(short port) {
-        this.port = port;
-        return this;
-    }
-
-    /**
-     * Get the max length to send to the controller
-     * @return
-     */
-    public short getMaxLength() {
-        return this.maxLength;
-    }
-
-    /**
-     * Set the max length to send to the controller
-     * @param maxLength
-     */
-    public OFActionOutput setMaxLength(short maxLength) {
-        this.maxLength = maxLength;
-        return this;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.port = data.readShort();
-        this.maxLength = data.readShort();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(port);
-        data.writeShort(maxLength);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 367;
-        int result = super.hashCode();
-        result = prime * result + maxLength;
-        result = prime * result + port;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionOutput)) {
-            return false;
-        }
-        OFActionOutput other = (OFActionOutput) obj;
-        if (maxLength != other.maxLength) {
-            return false;
-        }
-        if (port != other.port) {
-            return false;
-        }
-        return true;
-    }
-
-    /* (non-Javadoc)
-     * @see java.lang.Object#toString()
-     */
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(type);
-        builder.append("[");
-        builder.append(port);
-        builder.append("]");
-        return builder.toString();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java b/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java
deleted file mode 100644
index f79c84d39..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-
-/**
- * Represents an ofp_action_strip_vlan
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public class OFActionStripVirtualLan extends OFAction {
-    public static int MINIMUM_LENGTH = 8;
-
-    public OFActionStripVirtualLan() {
-        super();
-        super.setType(OFActionType.STRIP_VLAN);
-        super.setLength((short) MINIMUM_LENGTH);
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        // PAD
-        data.readInt();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        // PAD
-        data.writeInt(0);
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(type);
-        return builder.toString();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java b/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java
deleted file mode 100644
index 696c1c7a2..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_action_tp_port
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public abstract class OFActionTransportLayer extends OFAction {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected short transportPort;
-
-    /**
-     * @return the transportPort
-     */
-    public short getTransportPort() {
-        return transportPort;
-    }
-
-    /**
-     * @param transportPort the transportPort to set
-     */
-    public void setTransportPort(short transportPort) {
-        this.transportPort = transportPort;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.transportPort = data.readShort();
-        data.readShort();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.transportPort);
-        data.writeShort((short) 0);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 373;
-        int result = super.hashCode();
-        result = prime * result + transportPort;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionTransportLayer)) {
-            return false;
-        }
-        OFActionTransportLayer other = (OFActionTransportLayer) obj;
-        if (transportPort != other.transportPort) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(type);
-        builder.append("[");
-        builder.append(transportPort);
-        builder.append("]");
-        return builder.toString();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java b/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java
deleted file mode 100644
index 7e7b0f1fc..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.action;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFActionTransportLayerDestination extends OFActionTransportLayer {
-    public OFActionTransportLayerDestination() {
-        super();
-        super.setType(OFActionType.SET_TP_DST);
-        super.setLength((short) OFActionTransportLayer.MINIMUM_LENGTH);
-    }
-    
-    public OFActionTransportLayerDestination(short port) {
-        this();
-        this.transportPort = port;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java b/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java
deleted file mode 100644
index 385aa53c8..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.action;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFActionTransportLayerSource extends OFActionTransportLayer {
-    public OFActionTransportLayerSource() {
-        super();
-        super.setType(OFActionType.SET_TP_SRC);
-        super.setLength((short) OFActionTransportLayer.MINIMUM_LENGTH);
-    }
-    
-    public OFActionTransportLayerSource(short port) {
-        this();
-        this.transportPort = port;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionType.java b/src/main/java/org/openflow/protocol/action/OFActionType.java
deleted file mode 100644
index 18229170b..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionType.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol.action;
-
-import java.lang.reflect.Constructor;
-
-import org.openflow.protocol.Instantiable;
-
-/**
- * List of OpenFlow Action types and mappings to wire protocol value and
- * derived classes
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public enum OFActionType {
-    OUTPUT              (0, OFActionOutput.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionOutput();
-                            }}),
-    SET_VLAN_ID        (1, OFActionVirtualLanIdentifier.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionVirtualLanIdentifier();
-                            }}),
-    SET_VLAN_PCP        (2, OFActionVirtualLanPriorityCodePoint.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionVirtualLanPriorityCodePoint();
-                            }}),
-    STRIP_VLAN          (3, OFActionStripVirtualLan.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionStripVirtualLan();
-                            }}),
-    SET_DL_SRC          (4, OFActionDataLayerSource.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionDataLayerSource();
-                            }}),
-    SET_DL_DST          (5, OFActionDataLayerDestination.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionDataLayerDestination();
-                            }}),
-    SET_NW_SRC          (6, OFActionNetworkLayerSource.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionNetworkLayerSource();
-                            }}),
-    SET_NW_DST          (7, OFActionNetworkLayerDestination.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionNetworkLayerDestination();
-                            }}),
-    SET_NW_TOS          (8, OFActionNetworkTypeOfService.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionNetworkTypeOfService();
-                            }}),
-    SET_TP_SRC          (9, OFActionTransportLayerSource.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionTransportLayerSource();
-                            }}),
-    SET_TP_DST          (10, OFActionTransportLayerDestination.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionTransportLayerDestination();
-                            }}),
-    OPAQUE_ENQUEUE      (11, OFActionEnqueue.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionEnqueue();
-                            }}),
-    VENDOR              (0xffff, OFActionVendor.class, new Instantiable<OFAction>() {
-                            @Override
-                            public OFAction instantiate() {
-                                return new OFActionVendorGeneric();
-                            }});
-
-    protected static OFActionType[] mapping;
-
-    protected Class<? extends OFAction> clazz;
-    protected Constructor<? extends OFAction> constructor;
-    protected Instantiable<OFAction> instantiable;
-    protected int minLen;
-    protected short type;
-
-    /**
-     * Store some information about the OpenFlow Action type, including wire
-     * protocol type number, length, and derrived class
-     *
-     * @param type Wire protocol number associated with this OFType
-     * @param clazz The Java class corresponding to this type of OpenFlow Action
-     * @param instantiable the instantiable for the OFAction this type represents
-     */
-    OFActionType(int type, Class<? extends OFAction> clazz, Instantiable<OFAction> instantiable) {
-        this.type = (short) type;
-        this.clazz = clazz;
-        this.instantiable = instantiable;
-        try {
-            this.constructor = clazz.getConstructor(new Class[]{});
-        } catch (Exception e) {
-            throw new RuntimeException(
-                    "Failure getting constructor for class: " + clazz, e);
-        }
-        OFActionType.addMapping(this.type, this);
-    }
-
-    /**
-     * Adds a mapping from type value to OFActionType enum
-     *
-     * @param i OpenFlow wire protocol Action type value
-     * @param t type
-     */
-    static public void addMapping(short i, OFActionType t) {
-        if (mapping == null)
-            mapping = new OFActionType[16];
-        // bring higher mappings down to the edge of our array
-        if (i < 0)
-            i = (short) (16 + i);
-        OFActionType.mapping[i] = t;
-    }
-
-    /**
-     * Given a wire protocol OpenFlow type number, return the OFType associated
-     * with it
-     *
-     * @param i wire protocol number
-     * @return OFType enum type
-     */
-
-    static public OFActionType valueOf(short i) {
-        if (i < 0)
-            i = (short) (16+i);
-        return OFActionType.mapping[i];
-    }
-
-    /**
-     * @return Returns the wire protocol value corresponding to this
-     *         OFActionType
-     */
-    public short getTypeValue() {
-        return this.type;
-    }
-
-    /**
-     * @return return the OFAction subclass corresponding to this OFActionType
-     */
-    public Class<? extends OFAction> toClass() {
-        return clazz;
-    }
-
-    /**
-     * Returns the no-argument Constructor of the implementation class for
-     * this OFActionType
-     * @return the constructor
-     */
-    public Constructor<? extends OFAction> getConstructor() {
-        return constructor;
-    }
-
-    /**
-     * Returns a new instance of the OFAction represented by this OFActionType
-     * @return the new object
-     */
-    public OFAction newInstance() {
-        return instantiable.instantiate();
-    }
-
-    /**
-     * @return the instantiable
-     */
-    public Instantiable<OFAction> getInstantiable() {
-        return instantiable;
-    }
-
-    /**
-     * @param instantiable the instantiable to set
-     */
-    public void setInstantiable(Instantiable<OFAction> instantiable) {
-        this.instantiable = instantiable;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionVendor.java b/src/main/java/org/openflow/protocol/action/OFActionVendor.java
deleted file mode 100644
index 5860ef116..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionVendor.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol.action;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public abstract class OFActionVendor extends OFAction {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected int vendor;
-
-    public OFActionVendor() {
-        super();
-        super.setType(OFActionType.VENDOR);
-        super.setLength((short) MINIMUM_LENGTH);
-    }
-
-    /**
-     * @return the vendor
-     */
-    public int getVendor() {
-        return vendor;
-    }
-
-    /**
-     * @param vendor the vendor to set
-     */
-    public void setVendor(int vendor) {
-        this.vendor = vendor;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.vendor = data.readInt();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeInt(this.vendor);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 379;
-        int result = super.hashCode();
-        result = prime * result + vendor;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionVendor)) {
-            return false;
-        }
-        OFActionVendor other = (OFActionVendor) obj;
-        if (vendor != other.vendor) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        return super.toString() + "; vendor=" + vendor;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java b/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java
deleted file mode 100644
index 4f7859f5e..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol.action;
-
-
-import java.util.Arrays;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/** A generic / unparsed vendor action. This action is returned by
- *  BasicFactory.readFromWire if no more specific OFVendorActionFactory
- *  is registered.
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
- */
-public class OFActionVendorGeneric extends OFActionVendor {
-    public static int MINIMUM_LENGTH = 8;
-
-    private final static byte[] EMPTY_ARRAY = new byte[0];
-
-    protected byte[] vendorData;
-
-    public OFActionVendorGeneric() {
-        super();
-    }
-
-    public byte[] getVendorData() {
-        return vendorData;
-    }
-
-    public void setVendorData(byte[] vendorData) {
-        this.vendorData = vendorData;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-
-        int vendorDataLength = this.getLength() - MINIMUM_LENGTH;
-        if (vendorDataLength > 0) {
-            vendorData = new byte[vendorDataLength];
-            data.readBytes(vendorData);
-        } else {
-            vendorData = EMPTY_ARRAY;
-        }
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeInt(this.vendor);
-        data.writeBytes(vendorData);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 379;
-        int result = super.hashCode();
-        result = prime * result + Arrays.hashCode(vendorData);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionVendorGeneric)) {
-            return false;
-        }
-        OFActionVendorGeneric other = (OFActionVendorGeneric) obj;
-        if (!Arrays.equals(vendorData, other.vendorData)) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java b/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java
deleted file mode 100644
index 5bd0e0bda..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_action_vlan_vid
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public class OFActionVirtualLanIdentifier extends OFAction {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected short virtualLanIdentifier;
-
-    public OFActionVirtualLanIdentifier() {
-        super.setType(OFActionType.SET_VLAN_ID);
-        super.setLength((short) MINIMUM_LENGTH);
-    }
-    
-    public OFActionVirtualLanIdentifier(short vlanId) {
-        this();
-        this.virtualLanIdentifier = vlanId;
-    }
-
-    /**
-     * @return the virtualLanIdentifier
-     */
-    public short getVirtualLanIdentifier() {
-        return virtualLanIdentifier;
-    }
-
-    /**
-     * @param virtualLanIdentifier the virtualLanIdentifier to set
-     */
-    public void setVirtualLanIdentifier(short virtualLanIdentifier) {
-        this.virtualLanIdentifier = virtualLanIdentifier;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.virtualLanIdentifier = data.readShort();
-        data.readShort();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.virtualLanIdentifier);
-        data.writeShort((short) 0);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 383;
-        int result = super.hashCode();
-        result = prime * result + virtualLanIdentifier;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionVirtualLanIdentifier)) {
-            return false;
-        }
-        OFActionVirtualLanIdentifier other = (OFActionVirtualLanIdentifier) obj;
-        if (virtualLanIdentifier != other.virtualLanIdentifier) {
-            return false;
-        }
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java b/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java
deleted file mode 100644
index 9202df33f..000000000
--- a/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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.
-**/
-
-/**
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-package org.openflow.protocol.action;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_action_vlan_pcp
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public class OFActionVirtualLanPriorityCodePoint extends OFAction {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected byte virtualLanPriorityCodePoint;
-
-    public OFActionVirtualLanPriorityCodePoint() {
-        super.setType(OFActionType.SET_VLAN_PCP);
-        super.setLength((short) MINIMUM_LENGTH);
-    }
-    
-    public OFActionVirtualLanPriorityCodePoint(byte priority) {
-        this();
-        this.virtualLanPriorityCodePoint = priority;
-    }
-
-    /**
-     * @return the virtualLanPriorityCodePoint
-     */
-    public byte getVirtualLanPriorityCodePoint() {
-        return virtualLanPriorityCodePoint;
-    }
-
-    /**
-     * @param virtualLanPriorityCodePoint the virtualLanPriorityCodePoint to set
-     */
-    public void setVirtualLanPriorityCodePoint(byte virtualLanPriorityCodePoint) {
-        this.virtualLanPriorityCodePoint = virtualLanPriorityCodePoint;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-        this.virtualLanPriorityCodePoint = data.readByte();
-        data.readShort(); // pad
-        data.readByte(); // pad
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeByte(this.virtualLanPriorityCodePoint);
-        data.writeShort((short) 0);
-        data.writeByte((byte) 0);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 389;
-        int result = super.hashCode();
-        result = prime * result + virtualLanPriorityCodePoint;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (!super.equals(obj)) {
-            return false;
-        }
-        if (!(obj instanceof OFActionVirtualLanPriorityCodePoint)) {
-            return false;
-        }
-        OFActionVirtualLanPriorityCodePoint other = (OFActionVirtualLanPriorityCodePoint) obj;
-        if (virtualLanPriorityCodePoint != other.virtualLanPriorityCodePoint) {
-            return false;
-        }
-        return true;
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/org/openflow/protocol/factory/BasicFactory.java b/src/main/java/org/openflow/protocol/factory/BasicFactory.java
deleted file mode 100644
index f484a167f..000000000
--- a/src/main/java/org/openflow/protocol/factory/BasicFactory.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol.factory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionType;
-import org.openflow.protocol.action.OFActionVendor;
-import org.openflow.protocol.statistics.OFStatistics;
-import org.openflow.protocol.statistics.OFStatisticsType;
-import org.openflow.protocol.statistics.OFVendorStatistics;
-import org.openflow.protocol.vendor.OFByteArrayVendorData;
-import org.openflow.protocol.vendor.OFVendorData;
-import org.openflow.protocol.vendor.OFVendorDataType;
-import org.openflow.protocol.vendor.OFVendorId;
-
-
-/**
- * A basic OpenFlow factory that supports naive creation of both Messages and
- * Actions.
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- *
- */
-public enum BasicFactory implements OFMessageFactory, OFActionFactory,
-        OFStatisticsFactory, OFVendorDataFactory {
-    SINGLETON_INSTANCE;
-
-
-    private final OFVendorActionRegistry vendorActionRegistry;
-
-    private BasicFactory() {
-        vendorActionRegistry = OFVendorActionRegistry.getInstance();
-    }
-
-    public static BasicFactory getInstance() {
-        return SINGLETON_INSTANCE;
-    }
-
-    /**
-     * create and return a new instance of a message for OFType t. Also injects
-     * factories for those message types that implement the *FactoryAware
-     * interfaces.
-     *
-     * @return a newly created instance that may be modified / used freely by
-     *         the caller
-     */
-    @Override
-    public OFMessage getMessage(OFType t) {
-        OFMessage message = t.newInstance();
-        injectFactories(message);
-        return message;
-    }
-
-    @Override
-    public List<OFMessage> parseMessage(ChannelBuffer data) throws MessageParseException {
-        List<OFMessage> msglist = new ArrayList<OFMessage>();
-        OFMessage msg = null;
-
-        while (data.readableBytes() >= OFMessage.MINIMUM_LENGTH) {
-            data.markReaderIndex();
-            msg = this.parseMessageOne(data);
-            if (msg == null) {
-                data.resetReaderIndex();
-                break;
-            }
-            else {
-                msglist.add(msg);
-            }
-        }
-
-        if (msglist.size() == 0) {
-            return null;
-        }
-        return msglist;
-
-    }
-
-    public OFMessage parseMessageOne(ChannelBuffer data) throws MessageParseException {
-        try {
-            OFMessage demux = new OFMessage();
-            OFMessage ofm = null;
-
-            if (data.readableBytes() < OFMessage.MINIMUM_LENGTH)
-                return ofm;
-
-            data.markReaderIndex();
-            demux.readFrom(data);
-            data.resetReaderIndex();
-
-            if (demux.getLengthU() > data.readableBytes())
-                return ofm;
-
-            ofm = getMessage(demux.getType());
-            if (ofm == null)
-                return null;
-
-            injectFactories(ofm);
-            ofm.readFrom(data);
-            if (OFMessage.class.equals(ofm.getClass())) {
-                // advance the position for un-implemented messages
-                data.readerIndex(data.readerIndex()+(ofm.getLengthU() -
-                        OFMessage.MINIMUM_LENGTH));
-            }
-
-            return ofm;
-        } catch (Exception e) {
-            /* Write the offending data along with the error message */
-            data.resetReaderIndex();
-            String msg =
-                    "Message Parse Error for packet:" +  dumpBuffer(data) +
-                    "\nException: " + e.toString();
-            data.resetReaderIndex();
-
-            throw new MessageParseException(msg, e);
-        }
-    }
-
-    private void injectFactories(OFMessage ofm) {
-        if (ofm instanceof OFActionFactoryAware) {
-            ((OFActionFactoryAware)ofm).setActionFactory(this);
-        }
-        if (ofm instanceof OFMessageFactoryAware) {
-            ((OFMessageFactoryAware)ofm).setMessageFactory(this);
-        }
-        if (ofm instanceof OFStatisticsFactoryAware) {
-            ((OFStatisticsFactoryAware)ofm).setStatisticsFactory(this);
-        }
-        if (ofm instanceof OFVendorDataFactoryAware) {
-            ((OFVendorDataFactoryAware)ofm).setVendorDataFactory(this);
-        }
-    }
-
-    @Override
-    public OFAction getAction(OFActionType t) {
-        return t.newInstance();
-    }
-
-    @Override
-    public List<OFAction> parseActions(ChannelBuffer data, int length) {
-        return parseActions(data, length, 0);
-    }
-
-    @Override
-    public List<OFAction> parseActions(ChannelBuffer data, int length, int limit) {
-        List<OFAction> results = new ArrayList<OFAction>();
-        OFAction demux = new OFAction();
-        OFAction ofa;
-        int end = data.readerIndex() + length;
-
-        while (limit == 0 || results.size() <= limit) {
-            if ((data.readableBytes() < OFAction.MINIMUM_LENGTH ||
-                (data.readerIndex() + OFAction.MINIMUM_LENGTH) > end))
-                return results;
-
-            data.markReaderIndex();
-            demux.readFrom(data);
-            data.resetReaderIndex();
-
-            if ((demux.getLengthU() > data.readableBytes() ||
-                (data.readerIndex() + demux.getLengthU()) > end))
-                return results;
-
-            ofa = parseActionOne(demux.getType(), data);
-            results.add(ofa);
-        }
-
-        return results;
-    }
-
-    private OFAction parseActionOne(OFActionType type, ChannelBuffer data) {
-        OFAction ofa;
-        data.markReaderIndex();
-        ofa = getAction(type);
-        ofa.readFrom(data);
-
-        if(type == OFActionType.VENDOR) {
-            OFActionVendor vendorAction = (OFActionVendor) ofa;
-
-            OFVendorActionFactory vendorActionFactory = vendorActionRegistry.get(vendorAction.getVendor());
-
-            if(vendorActionFactory != null) {
-                // if we have a specific vendorActionFactory for this vendor id,
-                // delegate to it for vendor-specific reparsing of the message
-                data.resetReaderIndex();
-                OFActionVendor newAction = vendorActionFactory.readFrom(data);
-                if(newAction != null)
-                    ofa = newAction;
-            }
-        }
-
-        if (OFAction.class.equals(ofa.getClass())) {
-            // advance the position for un-implemented messages
-            data.readerIndex(data.readerIndex()+(ofa.getLengthU() -
-                    OFAction.MINIMUM_LENGTH));
-        }
-        return ofa;
-    }
-
-    @Override
-    public OFActionFactory getActionFactory() {
-        return this;
-    }
-
-    @Override
-    public OFStatistics getStatistics(OFType t, OFStatisticsType st) {
-        return st.newInstance(t);
-    }
-
-    @Override
-    public List<OFStatistics> parseStatistics(OFType t, OFStatisticsType st,
-                                              ChannelBuffer data, int length) {
-        return parseStatistics(t, st, data, length, 0);
-    }
-
-    /**
-     * @param t
-     *            OFMessage type: should be one of stats_request or stats_reply
-     * @param st
-     *            statistics type of this message, e.g., DESC, TABLE
-     * @param data
-     *            buffer to read from
-     * @param length
-     *            length of statistics
-     * @param limit
-     *            number of statistics to grab; 0 == all
-     *
-     * @return list of statistics
-     */
-
-    @Override
-    public List<OFStatistics> parseStatistics(OFType t, OFStatisticsType st,
-            ChannelBuffer data, int length, int limit) {
-        List<OFStatistics> results = new ArrayList<OFStatistics>();
-        OFStatistics statistics = getStatistics(t, st);
-
-        int start = data.readerIndex();
-        int count = 0;
-
-        while (limit == 0 || results.size() <= limit) {
-            // TODO Create a separate MUX/DEMUX path for vendor stats
-            if (statistics instanceof OFVendorStatistics)
-                ((OFVendorStatistics)statistics).setLength(length);
-
-            /**
-             * can't use data.remaining() here, b/c there could be other data
-             * buffered past this message
-             */
-            if ((length - count) >= statistics.getLength()) {
-                if (statistics instanceof OFActionFactoryAware)
-                    ((OFActionFactoryAware)statistics).setActionFactory(this);
-                statistics.readFrom(data);
-                results.add(statistics);
-                count += statistics.getLength();
-                statistics = getStatistics(t, st);
-            } else {
-                if (count < length) {
-                    /**
-                     * Nasty case: partial/incomplete statistic found even
-                     * though we have a full message. Found when NOX sent
-                     * agg_stats request with wrong agg statistics length (52
-                     * instead of 56)
-                     *
-                     * just throw the rest away, or we will break framing
-                     */
-                    data.readerIndex(start + length);
-                }
-                return results;
-            }
-        }
-        return results; // empty; no statistics at all
-    }
-
-
-    @Override
-    public OFVendorData getVendorData(OFVendorId vendorId,
-                                      OFVendorDataType vendorDataType) {
-        if (vendorDataType == null)
-            return null;
-
-        return vendorDataType.newInstance();
-    }
-
-    /**
-     * Attempts to parse and return the OFVendorData contained in the given
-     * ChannelBuffer, beginning right after the vendor id.
-     * @param vendor the vendor id that was parsed from the OFVendor message.
-     * @param data the ChannelBuffer from which to parse the vendor data
-     * @param length the length to the end of the enclosing message.
-     * @return an OFVendorData instance
-     */
-    @Override
-    public OFVendorData parseVendorData(int vendor, ChannelBuffer data,
-            int length) {
-        OFVendorDataType vendorDataType = null;
-        OFVendorId vendorId = OFVendorId.lookupVendorId(vendor);
-        if (vendorId != null) {
-            data.markReaderIndex();
-            vendorDataType = vendorId.parseVendorDataType(data, length);
-            data.resetReaderIndex();
-        }
-
-        OFVendorData vendorData = getVendorData(vendorId, vendorDataType);
-        if (vendorData == null)
-            vendorData = new OFByteArrayVendorData();
-
-        vendorData.readFrom(data, length);
-
-        return vendorData;
-    }
-
-    public static String dumpBuffer(ChannelBuffer data) {
-        // NOTE: Reads all the bytes in buffer from current read offset.
-        // Set/Reset ReaderIndex if you want to read from a different location
-        int len = data.readableBytes();
-        StringBuffer sb = new StringBuffer();
-        for (int i=0 ; i<len; i++) {
-            if (i%32 == 0) sb.append("\n");
-            if (i%4 == 0) sb.append(" ");
-            sb.append(String.format("%02x", data.getUnsignedByte(i)));
-        }
-        return sb.toString();
-    }
-
-}
diff --git a/src/main/java/org/openflow/protocol/factory/MessageParseException.java b/src/main/java/org/openflow/protocol/factory/MessageParseException.java
deleted file mode 100644
index 20f381ef8..000000000
--- a/src/main/java/org/openflow/protocol/factory/MessageParseException.java
+++ /dev/null
@@ -1,45 +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 org.openflow.protocol.factory;
-
-/**
- * Exception thrown when an openflow message fails to parse properly
- */
-public class MessageParseException extends Exception {
-    /**
-     * 
-     */
-    private static final long serialVersionUID = -75893812926304726L;
-
-    public MessageParseException() {
-        super();
-    }
-
-    public MessageParseException(String message, Throwable cause) {
-        super(message, cause);
-        this.setStackTrace(cause.getStackTrace());
-    }
-
-    public MessageParseException(String message) {
-        super(message);
-    }
-
-    public MessageParseException(Throwable cause) {
-        super(cause);
-        this.setStackTrace(cause.getStackTrace());
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFActionFactory.java b/src/main/java/org/openflow/protocol/factory/OFActionFactory.java
deleted file mode 100644
index c3cd06265..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFActionFactory.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.factory;
-
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionType;
-
-
-/**
- * The interface to factories used for retrieving OFAction instances. All
- * methods are expected to be thread-safe.
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public interface OFActionFactory {
-    /**
-     * Retrieves an OFAction instance corresponding to the specified
-     * OFActionType
-     * @param t the type of the OFAction to be retrieved
-     * @return an OFAction instance
-     */
-    public OFAction getAction(OFActionType t);
-
-    /**
-     * Attempts to parse and return all OFActions contained in the given
-     * ByteBuffer, beginning at the ByteBuffer's position, and ending at
-     * position+length.
-     * @param data the ChannelBuffer to parse for OpenFlow actions
-     * @param length the number of Bytes to examine for OpenFlow actions
-     * @return a list of OFAction instances
-     */
-    public List<OFAction> parseActions(ChannelBuffer data, int length);
-
-    /**
-     * Attempts to parse and return all OFActions contained in the given
-     * ByteBuffer, beginning at the ByteBuffer's position, and ending at
-     * position+length.
-     * @param data the ChannelBuffer to parse for OpenFlow actions
-     * @param length the number of Bytes to examine for OpenFlow actions
-     * @param limit the maximum number of messages to return, 0 means no limit
-     * @return a list of OFAction instances
-     */
-    public List<OFAction> parseActions(ChannelBuffer data, int length, int limit);
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java b/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java
deleted file mode 100644
index a97a95c0a..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.factory;
-
-/**
- * Objects implementing this interface are expected to be instantiated with an
- * instance of an OFActionFactory
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public interface OFActionFactoryAware {
-    /**
-     * Sets the OFActionFactory
-     * @param actionFactory
-     */
-    public void setActionFactory(OFActionFactory actionFactory);
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java b/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java
deleted file mode 100644
index 8bb704546..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.factory;
-
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFType;
-
-
-/**
- * The interface to factories used for retrieving OFMessage instances. All
- * methods are expected to be thread-safe.
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public interface OFMessageFactory {
-    /**
-     * Retrieves an OFMessage instance corresponding to the specified OFType
-     * @param t the type of the OFMessage to be retrieved
-     * @return an OFMessage instance
-     */
-    public OFMessage getMessage(OFType t);
-
-    /**
-     * Attempts to parse and return a OFMessages contained in the given
-     * ChannelBuffer, beginning at the ChannelBuffer's position, and ending at the
-     * after the first parsed message
-     * @param data the ChannelBuffer to parse for an OpenFlow message
-     * @return a list of OFMessage instances
-     * @throws MessageParseException 
-     */
-    public List<OFMessage> parseMessage(ChannelBuffer data) throws MessageParseException;
-
-    /**
-     * Retrieves an OFActionFactory
-     * @return an OFActionFactory
-     */
-    public OFActionFactory getActionFactory();
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java b/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java
deleted file mode 100644
index adb1421e1..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.factory;
-
-/**
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- *
- */
-public interface OFMessageFactoryAware {
-
-       /**
-        * Sets the message factory for this object
-        * 
-        * @param factory
-        */
-       void setMessageFactory(OFMessageFactory factory);
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java b/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java
deleted file mode 100644
index 32eb3cbff..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.factory;
-
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.statistics.OFStatistics;
-import org.openflow.protocol.statistics.OFStatisticsType;
-
-
-/**
- * The interface to factories used for retrieving OFStatistics instances. All
- * methods are expected to be thread-safe.
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public interface OFStatisticsFactory {
-    /**
-     * Retrieves an OFStatistics instance corresponding to the specified
-     * OFStatisticsType
-     * @param t the type of the containing OFMessage, only accepts statistics
-     *           request or reply
-     * @param st the type of the OFStatistics to be retrieved
-     * @return an OFStatistics instance
-     */
-    public OFStatistics getStatistics(OFType t, OFStatisticsType st);
-
-    /**
-     * Attempts to parse and return all OFStatistics contained in the given
-     * ByteBuffer, beginning at the ByteBuffer's position, and ending at
-     * position+length.
-     * @param t the type of the containing OFMessage, only accepts statistics
-     *           request or reply
-     * @param st the type of the OFStatistics to be retrieved
-     * @param data the ChannelBuffer to parse for OpenFlow Statistics
-     * @param length the number of Bytes to examine for OpenFlow Statistics
-     * @return a list of OFStatistics instances
-     */
-    public List<OFStatistics> parseStatistics(OFType t,
-            OFStatisticsType st, ChannelBuffer data, int length);
-
-    /**
-     * Attempts to parse and return all OFStatistics contained in the given
-     * ByteBuffer, beginning at the ByteBuffer's position, and ending at
-     * position+length.
-     * @param t the type of the containing OFMessage, only accepts statistics
-     *           request or reply
-     * @param st the type of the OFStatistics to be retrieved
-     * @param data the ChannelBuffer to parse for OpenFlow Statistics
-     * @param length the number of Bytes to examine for OpenFlow Statistics
-     * @param limit the maximum number of messages to return, 0 means no limit
-     * @return a list of OFStatistics instances
-     */
-    public List<OFStatistics> parseStatistics(OFType t,
-            OFStatisticsType st, ChannelBuffer data, int length, int limit);
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java b/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java
deleted file mode 100644
index 52ab09a95..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.factory;
-
-/**
- * Objects implementing this interface are expected to be instantiated with an
- * instance of an OFStatisticsFactory
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public interface OFStatisticsFactoryAware {
-    /**
-     * Sets the OFStatisticsFactory
-     * @param statisticsFactory
-     */
-    public void setStatisticsFactory(OFStatisticsFactory statisticsFactory);
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java b/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java
deleted file mode 100644
index eb89810b7..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java
+++ /dev/null
@@ -1,43 +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 org.openflow.protocol.factory;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.action.OFActionVendor;
-
-/** Interface contract for an actionfactory that creates vendor-specific actions.
- *  VendorActionFactories are registered with the BasicFactory for a specific
- *  vendor id.
- *  <p>
- *  <b>Note:</b> Implementations are expected to be thread-safe.
- *
- * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
- */
-public interface OFVendorActionFactory {
-
-    /** parse the data from the wire, create and return a vendor-specific action.
-     *
-     * @param data contains a serialized vendor action at the current readerPosition.
-     *    The full message is guaranteed to be available in the buffer.
-     *
-     * @return upon success returns a newly allocated vendor-specific
-     *   action instance, and advances the readerPosition in data for the
-     *   entire length. Upon failure, returns null and leaves the readerPosition
-     *   in data unmodified.
-     */
-    OFActionVendor readFrom(ChannelBuffer data);
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java b/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java
deleted file mode 100644
index 1f556812c..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java
+++ /dev/null
@@ -1,50 +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 org.openflow.protocol.factory;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/** Singleton registry object that holds a mapping from vendor ids to vendor-specific
- *  mapping factories. Threadsafe.
- *
- * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
- */
-public class OFVendorActionRegistry {
-    private static class InstanceHolder {
-        private final static OFVendorActionRegistry instance = new OFVendorActionRegistry();
-    }
-
-    public static OFVendorActionRegistry getInstance() {
-        return InstanceHolder.instance;
-    }
-    private final Map <Integer, OFVendorActionFactory> vendorActionFactories;
-
-    public OFVendorActionRegistry() {
-        vendorActionFactories = new ConcurrentHashMap<Integer, OFVendorActionFactory>();
-    }
-
-    public OFVendorActionFactory register(int vendorId, OFVendorActionFactory factory) {
-        return vendorActionFactories.put(vendorId, factory);
-    }
-
-    public OFVendorActionFactory get(int vendorId) {
-        return vendorActionFactories.get(vendorId);
-    }
-
-
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java b/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java
deleted file mode 100644
index d754a4a31..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.protocol.factory;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.vendor.OFVendorData;
-import org.openflow.protocol.vendor.OFVendorDataType;
-import org.openflow.protocol.vendor.OFVendorId;
-
-/**
- * The interface to factories used for parsing/creating OFVendorData instances.
- * All methods are expected to be thread-safe.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public interface OFVendorDataFactory {
-    /**
-     * Retrieves an OFVendorData instance corresponding to the specified
-     * OFVendorId and OFVendorDataType. There are 3 possible cases for
-     * how this will be called:
-     * 
-     * 1) If the vendor id in the OFVendor message is an unknown value, 
-     *    then this method is called with both vendorId and vendorDataType
-     *    set to null. In this case typically the factory method should
-     *    return an instance of OFGenericVendorData that just contains
-     *    the raw byte array of the vendor data.
-     *    
-     * 2) If the vendor id is known but no vendor data type has been
-     *    registered for the data in the message, then vendorId is set to
-     *    the appropriate OFVendorId instance and OFVendorDataType is set
-     *    to null. This would typically be handled the same way as #1
-     *    
-     * 3) If both the vendor id and and vendor data type are known, then
-     *    typically you'd just call the method in OFVendorDataType to
-     *    instantiate the appropriate subclass of OFVendorData.
-     *    
-     * @param vendorId the vendorId of the containing OFVendor message
-     * @param vendorDataType the type of the OFVendorData to be retrieved
-     * @return an OFVendorData instance
-     */
-    public OFVendorData getVendorData(OFVendorId vendorId,
-            OFVendorDataType vendorDataType);
-    
-    /**
-     * Attempts to parse and return the OFVendorData contained in the given
-     * ChannelBuffer, beginning right after the vendor id.
-     * @param vendorId the vendor id that was parsed from the OFVendor message.
-     * @param data the ChannelBuffer from which to parse the vendor data
-     * @param length the length to the end of the enclosing message.
-     * @return an OFVendorData instance
-     */
-    public OFVendorData parseVendorData(int vendorId, ChannelBuffer data,
-            int length);
-}
diff --git a/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java b/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java
deleted file mode 100644
index 23614b0d0..000000000
--- a/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.protocol.factory;
-
-/**
- * Classes implementing this interface are expected to be instantiated with an
- * instance of an OFVendorDataFactory
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public interface OFVendorDataFactoryAware {
-    public void setVendorDataFactory(OFVendorDataFactory vendorDataFactory);
-}
diff --git a/src/main/java/org/openflow/protocol/serializers/OFFeaturesReplyJSONSerializer.java b/src/main/java/org/openflow/protocol/serializers/OFFeaturesReplyJSONSerializer.java
deleted file mode 100644
index 1102dc786..000000000
--- a/src/main/java/org/openflow/protocol/serializers/OFFeaturesReplyJSONSerializer.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    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 org.openflow.protocol.serializers;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import org.openflow.protocol.OFFeaturesReply;
-import org.openflow.util.HexString;
-
-public class OFFeaturesReplyJSONSerializer extends JsonSerializer<OFFeaturesReply> {
-    
-    /**
-     * Performs the serialization of a OFFeaturesReply object
-     */
-    @Override
-    public void serialize(OFFeaturesReply reply, JsonGenerator jGen, SerializerProvider serializer) throws IOException, JsonProcessingException {
-        jGen.writeStartObject();
-        jGen.writeNumberField("actions", reply.getActions());
-        jGen.writeNumberField("buffers", reply.getBuffers());
-        jGen.writeNumberField("capabilities", reply.getCapabilities());
-        jGen.writeStringField("datapathId", HexString.toHexString(reply.getDatapathId()));
-        jGen.writeNumberField("length", reply.getLength());
-        serializer.defaultSerializeField("ports", reply.getPorts(), jGen);
-        jGen.writeNumberField("tables", reply.getTables());
-        jGen.writeStringField("type", reply.getType().toString());
-        jGen.writeNumberField("version", reply.getVersion());
-        jGen.writeNumberField("xid", reply.getXid());
-        jGen.writeEndObject();
-    }
-
-    /**
-     * Tells SimpleModule that we are the serializer for OFFeaturesReply
-     */
-    @Override
-    public Class<OFFeaturesReply> handledType() {
-        return OFFeaturesReply.class;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/serializers/OFMatchJSONSerializer.java b/src/main/java/org/openflow/protocol/serializers/OFMatchJSONSerializer.java
deleted file mode 100644
index 2ae2d1c46..000000000
--- a/src/main/java/org/openflow/protocol/serializers/OFMatchJSONSerializer.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    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 org.openflow.protocol.serializers;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonSerializer;
-import com.fasterxml.jackson.databind.SerializerProvider;
-import org.openflow.protocol.OFMatch;
-import org.openflow.util.HexString;
-
-public class OFMatchJSONSerializer extends JsonSerializer<OFMatch> {
-
-    /**
-     * Converts an IP in a 32 bit integer to a dotted-decimal string
-     * @param i The IP address in a 32 bit integer
-     * @return An IP address string in dotted-decimal
-     */
-    private String intToIp(int i) {
-        return ((i >> 24 ) & 0xFF) + "." +
-               ((i >> 16 ) & 0xFF) + "." +
-               ((i >>  8 ) & 0xFF) + "." +
-               ( i        & 0xFF);
-    }
-
-    /**
-     * Performs the serialization of a OFMatch object
-     */
-    @Override
-    public void serialize(OFMatch match, JsonGenerator jGen, 
-                                SerializerProvider serializer) 
-                                throws IOException, JsonProcessingException {
-        jGen.writeStartObject();
-        jGen.writeStringField("dataLayerDestination", 
-                    HexString.toHexString(match.getDataLayerDestination()));
-        jGen.writeStringField("dataLayerSource", 
-                    HexString.toHexString(match.getDataLayerSource()));
-        String dataType = Integer.toHexString(match.getDataLayerType());
-        while (dataType.length() < 4) {
-            dataType = "0".concat(dataType);
-        }
-        jGen.writeStringField("dataLayerType", "0x" + dataType);
-        jGen.writeNumberField("dataLayerVirtualLan", 
-                    match.getDataLayerVirtualLan());
-        jGen.writeNumberField("dataLayerVirtualLanPriorityCodePoint", 
-                    match.getDataLayerVirtualLanPriorityCodePoint());
-        jGen.writeNumberField("inputPort", match.getInputPort());
-        jGen.writeStringField("networkDestination", 
-                    intToIp(match.getNetworkDestination()));
-        jGen.writeNumberField("networkDestinationMaskLen", 
-                    match.getNetworkDestinationMaskLen());
-        jGen.writeNumberField("networkProtocol", match.getNetworkProtocol());
-        jGen.writeStringField("networkSource", 
-                    intToIp(match.getNetworkSource()));
-        jGen.writeNumberField("networkSourceMaskLen", 
-                    match.getNetworkSourceMaskLen());
-        jGen.writeNumberField("networkTypeOfService", 
-                    match.getNetworkTypeOfService());
-        jGen.writeNumberField("transportDestination", 
-                    match.getTransportDestination());
-        jGen.writeNumberField("transportSource", 
-                    match.getTransportSource());
-        jGen.writeNumberField("wildcards", match.getWildcards());
-        jGen.writeEndObject();
-    }
-
-    /**
-     * Tells SimpleModule that we are the serializer for OFMatch
-     */
-    @Override
-    public Class<OFMatch> handledType() {
-        return OFMatch.class;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/serializers/StringDpidToLongJSONDeserializer.java b/src/main/java/org/openflow/protocol/serializers/StringDpidToLongJSONDeserializer.java
deleted file mode 100644
index 60c5a664e..000000000
--- a/src/main/java/org/openflow/protocol/serializers/StringDpidToLongJSONDeserializer.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.openflow.protocol.serializers;
-
-import java.io.IOException;
-
-import org.openflow.util.HexString;
-
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.DeserializationContext;
-import com.fasterxml.jackson.databind.JsonDeserializer;
-
-public class StringDpidToLongJSONDeserializer extends
-    JsonDeserializer<Long> {
-
-    @Override
-    public Long deserialize(JsonParser jsonParser,
-                                       DeserializationContext cntx)
-                                       throws IOException,
-                                       JsonProcessingException {
-        return Long.valueOf(HexString.toLong(jsonParser.getText()));
-    }
-
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java b/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java
deleted file mode 100644
index 0c86006b0..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_aggregate_stats_reply structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFAggregateStatisticsReply implements OFStatistics {
-    protected long packetCount;
-    protected long byteCount;
-    protected int flowCount;
-
-    /**
-     * @return the packetCount
-     */
-    public long getPacketCount() {
-        return packetCount;
-    }
-
-    /**
-     * @param packetCount the packetCount to set
-     */
-    public void setPacketCount(long packetCount) {
-        this.packetCount = packetCount;
-    }
-
-    /**
-     * @return the byteCount
-     */
-    public long getByteCount() {
-        return byteCount;
-    }
-
-    /**
-     * @param byteCount the byteCount to set
-     */
-    public void setByteCount(long byteCount) {
-        this.byteCount = byteCount;
-    }
-
-    /**
-     * @return the flowCount
-     */
-    public int getFlowCount() {
-        return flowCount;
-    }
-
-    /**
-     * @param flowCount the flowCount to set
-     */
-    public void setFlowCount(int flowCount) {
-        this.flowCount = flowCount;
-    }
-
-    @Override
-    @JsonIgnore
-    public int getLength() {
-        return 24;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.packetCount = data.readLong();
-        this.byteCount = data.readLong();
-        this.flowCount = data.readInt();
-        data.readInt(); // pad
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeLong(this.packetCount);
-        data.writeLong(this.byteCount);
-        data.writeInt(this.flowCount);
-        data.writeInt(0); // pad
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 397;
-        int result = 1;
-        result = prime * result + (int) (byteCount ^ (byteCount >>> 32));
-        result = prime * result + flowCount;
-        result = prime * result + (int) (packetCount ^ (packetCount >>> 32));
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFAggregateStatisticsReply)) {
-            return false;
-        }
-        OFAggregateStatisticsReply other = (OFAggregateStatisticsReply) obj;
-        if (byteCount != other.byteCount) {
-            return false;
-        }
-        if (flowCount != other.flowCount) {
-            return false;
-        }
-        if (packetCount != other.packetCount) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java b/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java
deleted file mode 100644
index f41a4f1d5..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.OFMatch;
-
-/**
- * Represents an ofp_aggregate_stats_request structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFAggregateStatisticsRequest implements OFStatistics {
-    protected OFMatch match;
-    protected byte tableId;
-    protected short outPort;
-
-    /**
-     * @return the match
-     */
-    public OFMatch getMatch() {
-        return match;
-    }
-
-    /**
-     * @param match the match to set
-     */
-    public void setMatch(OFMatch match) {
-        this.match = match;
-    }
-
-    /**
-     * @return the tableId
-     */
-    public byte getTableId() {
-        return tableId;
-    }
-
-    /**
-     * @param tableId the tableId to set
-     */
-    public void setTableId(byte tableId) {
-        this.tableId = tableId;
-    }
-
-    /**
-     * @return the outPort
-     */
-    public short getOutPort() {
-        return outPort;
-    }
-
-    /**
-     * @param outPort the outPort to set
-     */
-    public void setOutPort(short outPort) {
-        this.outPort = outPort;
-    }
-
-    @Override
-    public int getLength() {
-        return 44;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        if (this.match == null)
-            this.match = new OFMatch();
-        this.match.readFrom(data);
-        this.tableId = data.readByte();
-        data.readByte(); // pad
-        this.outPort = data.readShort();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        this.match.writeTo(data);
-        data.writeByte(this.tableId);
-        data.writeByte((byte) 0);
-        data.writeShort(this.outPort);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 401;
-        int result = 1;
-        result = prime * result + ((match == null) ? 0 : match.hashCode());
-        result = prime * result + outPort;
-        result = prime * result + tableId;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFAggregateStatisticsRequest)) {
-            return false;
-        }
-        OFAggregateStatisticsRequest other = (OFAggregateStatisticsRequest) obj;
-        if (match == null) {
-            if (other.match != null) {
-                return false;
-            }
-        } else if (!match.equals(other.match)) {
-            return false;
-        }
-        if (outPort != other.outPort) {
-            return false;
-        }
-        if (tableId != other.tableId) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java b/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java
deleted file mode 100644
index 5e6586f0d..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol.statistics;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.StringByteSerializer;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
-/**
- * Represents an ofp_desc_stats structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFDescriptionStatistics implements OFStatistics {
-    public static int DESCRIPTION_STRING_LENGTH = 256;
-    public static int SERIAL_NUMBER_LENGTH = 32;
-
-    protected String manufacturerDescription;
-    protected String hardwareDescription;
-    protected String softwareDescription;
-    protected String serialNumber;
-    protected String datapathDescription;
-
-
-    /**
-     *
-     */
-    public OFDescriptionStatistics() {
-    }
-
-    /**
-     * Copy constructor
-     */
-    public OFDescriptionStatistics(OFDescriptionStatistics other) {
-        manufacturerDescription = other.manufacturerDescription;
-        hardwareDescription = other.hardwareDescription;
-        softwareDescription = other.softwareDescription;
-        serialNumber = other.serialNumber;
-        datapathDescription = other.datapathDescription;
-    }
-
-    /**
-     * @return the manufacturerDescription
-     */
-    public String getManufacturerDescription() {
-        return manufacturerDescription;
-    }
-
-    /**
-     * @param manufacturerDescription the manufacturerDescription to set
-     */
-    public void setManufacturerDescription(String manufacturerDescription) {
-        this.manufacturerDescription = manufacturerDescription;
-    }
-
-    /**
-     * @return the hardwareDescription
-     */
-    public String getHardwareDescription() {
-        return hardwareDescription;
-    }
-
-    /**
-     * @param hardwareDescription the hardwareDescription to set
-     */
-    public void setHardwareDescription(String hardwareDescription) {
-        this.hardwareDescription = hardwareDescription;
-    }
-
-    /**
-     * @return the softwareDescription
-     */
-    public String getSoftwareDescription() {
-        return softwareDescription;
-    }
-
-    /**
-     * @param softwareDescription the softwareDescription to set
-     */
-    public void setSoftwareDescription(String softwareDescription) {
-        this.softwareDescription = softwareDescription;
-    }
-
-    /**
-     * @return the serialNumber
-     */
-    public String getSerialNumber() {
-        return serialNumber;
-    }
-
-    /**
-     * @param serialNumber the serialNumber to set
-     */
-    public void setSerialNumber(String serialNumber) {
-        this.serialNumber = serialNumber;
-    }
-
-    /**
-     * @return the datapathDescription
-     */
-    public String getDatapathDescription() {
-        return datapathDescription;
-    }
-
-    /**
-     * @param datapathDescription the datapathDescription to set
-     */
-    public void setDatapathDescription(String datapathDescription) {
-        this.datapathDescription = datapathDescription;
-    }
-
-    @Override
-    @JsonIgnore
-    public int getLength() {
-        return 1056;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.manufacturerDescription = StringByteSerializer.readFrom(data,
-                DESCRIPTION_STRING_LENGTH);
-        this.hardwareDescription = StringByteSerializer.readFrom(data,
-                DESCRIPTION_STRING_LENGTH);
-        this.softwareDescription = StringByteSerializer.readFrom(data,
-                DESCRIPTION_STRING_LENGTH);
-        this.serialNumber = StringByteSerializer.readFrom(data,
-                SERIAL_NUMBER_LENGTH);
-        this.datapathDescription = StringByteSerializer.readFrom(data,
-                DESCRIPTION_STRING_LENGTH);
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH,
-                this.manufacturerDescription);
-        StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH,
-                this.hardwareDescription);
-        StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH,
-                this.softwareDescription);
-        StringByteSerializer.writeTo(data, SERIAL_NUMBER_LENGTH,
-                this.serialNumber);
-        StringByteSerializer.writeTo(data, DESCRIPTION_STRING_LENGTH,
-                this.datapathDescription);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 409;
-        int result = 1;
-        result = prime
-                * result
-                + ((datapathDescription == null) ? 0 : datapathDescription
-                        .hashCode());
-        result = prime
-                * result
-                + ((hardwareDescription == null) ? 0 : hardwareDescription
-                        .hashCode());
-        result = prime
-                * result
-                + ((manufacturerDescription == null) ? 0
-                        : manufacturerDescription.hashCode());
-        result = prime * result
-                + ((serialNumber == null) ? 0 : serialNumber.hashCode());
-        result = prime
-                * result
-                + ((softwareDescription == null) ? 0 : softwareDescription
-                        .hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFDescriptionStatistics)) {
-            return false;
-        }
-        OFDescriptionStatistics other = (OFDescriptionStatistics) obj;
-        if (datapathDescription == null) {
-            if (other.datapathDescription != null) {
-                return false;
-            }
-        } else if (!datapathDescription.equals(other.datapathDescription)) {
-            return false;
-        }
-        if (hardwareDescription == null) {
-            if (other.hardwareDescription != null) {
-                return false;
-            }
-        } else if (!hardwareDescription.equals(other.hardwareDescription)) {
-            return false;
-        }
-        if (manufacturerDescription == null) {
-            if (other.manufacturerDescription != null) {
-                return false;
-            }
-        } else if (!manufacturerDescription
-                .equals(other.manufacturerDescription)) {
-            return false;
-        }
-        if (serialNumber == null) {
-            if (other.serialNumber != null) {
-                return false;
-            }
-        } else if (!serialNumber.equals(other.serialNumber)) {
-            return false;
-        }
-        if (softwareDescription == null) {
-            if (other.softwareDescription != null) {
-                return false;
-            }
-        } else if (!softwareDescription.equals(other.softwareDescription)) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        return "Switch Desc - Vendor: " +  manufacturerDescription +
-                "  Model: " + hardwareDescription +
-                "  Make: " + datapathDescription +
-                "  Version: " + softwareDescription +
-                "  S/N: " + serialNumber;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java b/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java
deleted file mode 100644
index 0aad88df7..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.factory.OFActionFactory;
-import org.openflow.protocol.factory.OFActionFactoryAware;
-import org.openflow.util.U16;
-
-/**
- * Represents an ofp_flow_stats structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFFlowStatisticsReply implements OFStatistics, OFActionFactoryAware {
-    public static int MINIMUM_LENGTH = 88;
-
-    protected OFActionFactory actionFactory;
-    protected short length = (short) MINIMUM_LENGTH;
-    protected byte tableId;
-    protected OFMatch match;
-    protected int durationSeconds;
-    protected int durationNanoseconds;
-    protected short priority;
-    protected short idleTimeout;
-    protected short hardTimeout;
-    protected long cookie;
-    protected long packetCount;
-    protected long byteCount;
-    protected List<OFAction> actions;
-
-    /**
-     * @return the tableId
-     */
-    public byte getTableId() {
-        return tableId;
-    }
-
-    /**
-     * @param tableId the tableId to set
-     */
-    public void setTableId(byte tableId) {
-        this.tableId = tableId;
-    }
-
-    /**
-     * @return the match
-     */
-    public OFMatch getMatch() {
-        return match;
-    }
-
-    /**
-     * @param match the match to set
-     */
-    public void setMatch(OFMatch match) {
-        this.match = match;
-    }
-
-    /**
-     * @return the durationSeconds
-     */
-    public int getDurationSeconds() {
-        return durationSeconds;
-    }
-
-    /**
-     * @param durationSeconds the durationSeconds to set
-     */
-    public void setDurationSeconds(int durationSeconds) {
-        this.durationSeconds = durationSeconds;
-    }
-
-    /**
-     * @return the durationNanoseconds
-     */
-    public int getDurationNanoseconds() {
-        return durationNanoseconds;
-    }
-
-    /**
-     * @param durationNanoseconds the durationNanoseconds to set
-     */
-    public void setDurationNanoseconds(int durationNanoseconds) {
-        this.durationNanoseconds = durationNanoseconds;
-    }
-
-    /**
-     * @return the priority
-     */
-    public short getPriority() {
-        return priority;
-    }
-
-    /**
-     * @param priority the priority to set
-     */
-    public void setPriority(short priority) {
-        this.priority = priority;
-    }
-
-    /**
-     * @return the idleTimeout
-     */
-    public short getIdleTimeout() {
-        return idleTimeout;
-    }
-
-    /**
-     * @param idleTimeout the idleTimeout to set
-     */
-    public void setIdleTimeout(short idleTimeout) {
-        this.idleTimeout = idleTimeout;
-    }
-
-    /**
-     * @return the hardTimeout
-     */
-    public short getHardTimeout() {
-        return hardTimeout;
-    }
-
-    /**
-     * @param hardTimeout the hardTimeout to set
-     */
-    public void setHardTimeout(short hardTimeout) {
-        this.hardTimeout = hardTimeout;
-    }
-
-    /**
-     * @return the cookie
-     */
-    public long getCookie() {
-        return cookie;
-    }
-
-    /**
-     * @param cookie the cookie to set
-     */
-    public void setCookie(long cookie) {
-        this.cookie = cookie;
-    }
-
-    /**
-     * @return the packetCount
-     */
-    public long getPacketCount() {
-        return packetCount;
-    }
-
-    /**
-     * @param packetCount the packetCount to set
-     */
-    public void setPacketCount(long packetCount) {
-        this.packetCount = packetCount;
-    }
-
-    /**
-     * @return the byteCount
-     */
-    public long getByteCount() {
-        return byteCount;
-    }
-
-    /**
-     * @param byteCount the byteCount to set
-     */
-    public void setByteCount(long byteCount) {
-        this.byteCount = byteCount;
-    }
-
-    /**
-     * @param length the length to set
-     */
-    public void setLength(short length) {
-        this.length = length;
-    }
-
-    @Override
-    @JsonIgnore
-    public int getLength() {
-        return U16.f(length);
-    }
-
-    /**
-     * @param actionFactory the actionFactory to set
-     */
-    @Override
-    public void setActionFactory(OFActionFactory actionFactory) {
-        this.actionFactory = actionFactory;
-    }
-
-    /**
-     * @return the actions
-     */
-    public List<OFAction> getActions() {
-        return actions;
-    }
-
-    /**
-     * @param actions the actions to set
-     */
-    public void setActions(List<OFAction> actions) {
-        this.actions = actions;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.length = data.readShort();
-        this.tableId = data.readByte();
-        data.readByte(); // pad
-        if (this.match == null)
-            this.match = new OFMatch();
-        this.match.readFrom(data);
-        this.durationSeconds = data.readInt();
-        this.durationNanoseconds = data.readInt();
-        this.priority = data.readShort();
-        this.idleTimeout = data.readShort();
-        this.hardTimeout = data.readShort();
-        data.readInt(); // pad
-        data.readShort(); // pad
-        this.cookie = data.readLong();
-        this.packetCount = data.readLong();
-        this.byteCount = data.readLong();
-        if (this.actionFactory == null)
-            throw new RuntimeException("OFActionFactory not set");
-        this.actions = this.actionFactory.parseActions(data, getLength() -
-                MINIMUM_LENGTH);
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeShort(this.length);
-        data.writeByte(this.tableId);
-        data.writeByte((byte) 0);
-        this.match.writeTo(data);
-        data.writeInt(this.durationSeconds);
-        data.writeInt(this.durationNanoseconds);
-        data.writeShort(this.priority);
-        data.writeShort(this.idleTimeout);
-        data.writeShort(this.hardTimeout);
-        data.writeInt(0); // pad
-        data.writeShort((short)0); // pad
-        data.writeLong(this.cookie);
-        data.writeLong(this.packetCount);
-        data.writeLong(this.byteCount);
-        if (actions != null) {
-            for (OFAction action : actions) {
-                action.writeTo(data);
-            }
-        }
-    }
-
-    @Override
-    public String toString() {
-    	String str = "match=" + this.match;
-    	str += " tableId=" + this.tableId;
-    	str += " durationSeconds=" + this.durationSeconds;
-    	str += " durationNanoseconds=" + this.durationNanoseconds;
-    	str += " priority=" + this.priority;
-    	str += " idleTimeout=" + this.idleTimeout;
-    	str += " hardTimeout=" + this.hardTimeout;
-        str += " cookie=" + Long.toHexString(this.cookie);
-    	str += " packetCount=" + this.packetCount;
-    	str += " byteCount=" + this.byteCount;
-    	str += " action=" + this.actions;
-    	
-    	return str;
-    }
-    
-    @Override
-    public int hashCode() {
-        final int prime = 419;
-        int result = 1;
-        result = prime * result + (int) (byteCount ^ (byteCount >>> 32));
-        result = prime * result + (int) (cookie ^ (cookie >>> 32));
-        result = prime * result + durationNanoseconds;
-        result = prime * result + durationSeconds;
-        result = prime * result + hardTimeout;
-        result = prime * result + idleTimeout;
-        result = prime * result + length;
-        result = prime * result + ((match == null) ? 0 : match.hashCode());
-        result = prime * result + (int) (packetCount ^ (packetCount >>> 32));
-        result = prime * result + priority;
-        result = prime * result + tableId;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFFlowStatisticsReply)) {
-            return false;
-        }
-        OFFlowStatisticsReply other = (OFFlowStatisticsReply) obj;
-        if (byteCount != other.byteCount) {
-            return false;
-        }
-        if (cookie != other.cookie) {
-            return false;
-        }
-        if (durationNanoseconds != other.durationNanoseconds) {
-            return false;
-        }
-        if (durationSeconds != other.durationSeconds) {
-            return false;
-        }
-        if (hardTimeout != other.hardTimeout) {
-            return false;
-        }
-        if (idleTimeout != other.idleTimeout) {
-            return false;
-        }
-        if (length != other.length) {
-            return false;
-        }
-        if (match == null) {
-            if (other.match != null) {
-                return false;
-            }
-        } else if (!match.equals(other.match)) {
-            return false;
-        }
-        if (packetCount != other.packetCount) {
-            return false;
-        }
-        if (priority != other.priority) {
-            return false;
-        }
-        if (tableId != other.tableId) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java b/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java
deleted file mode 100644
index b21de0c7f..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.OFMatch;
-
-/**
- * Represents an ofp_flow_stats_request structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFFlowStatisticsRequest implements OFStatistics {
-    protected OFMatch match;
-    protected byte tableId;
-    protected short outPort;
-
-    /**
-     * @return the match
-     */
-    public OFMatch getMatch() {
-        return match;
-    }
-
-    /**
-     * @param match the match to set
-     */
-    public void setMatch(OFMatch match) {
-        this.match = match;
-    }
-
-    /**
-     * @return the tableId
-     */
-    public byte getTableId() {
-        return tableId;
-    }
-
-    /**
-     * @param tableId the tableId to set
-     */
-    public void setTableId(byte tableId) {
-        this.tableId = tableId;
-    }
-
-    /**
-     * @return the outPort
-     */
-    public short getOutPort() {
-        return outPort;
-    }
-
-    /**
-     * @param outPort the outPort to set
-     */
-    public void setOutPort(short outPort) {
-        this.outPort = outPort;
-    }
-
-    @Override
-    public int getLength() {
-        return 44;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        if (this.match == null)
-            this.match = new OFMatch();
-        this.match.readFrom(data);
-        this.tableId = data.readByte();
-        data.readByte(); // pad
-        this.outPort = data.readShort();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        this.match.writeTo(data);
-        data.writeByte(this.tableId);
-        data.writeByte((byte) 0);
-        data.writeShort(this.outPort);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 421;
-        int result = 1;
-        result = prime * result + ((match == null) ? 0 : match.hashCode());
-        result = prime * result + outPort;
-        result = prime * result + tableId;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFFlowStatisticsRequest)) {
-            return false;
-        }
-        OFFlowStatisticsRequest other = (OFFlowStatisticsRequest) obj;
-        if (match == null) {
-            if (other.match != null) {
-                return false;
-            }
-        } else if (!match.equals(other.match)) {
-            return false;
-        }
-        if (outPort != other.outPort) {
-            return false;
-        }
-        if (tableId != other.tableId) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java b/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java
deleted file mode 100644
index 15192bbc4..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol.statistics;
-
-
-import net.floodlightcontroller.core.web.serializers.UShortSerializer;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_port_stats structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFPortStatisticsReply implements OFStatistics {
-    protected short portNumber;
-    protected long receivePackets;
-    protected long transmitPackets;
-    protected long receiveBytes;
-    protected long transmitBytes;
-    protected long receiveDropped;
-    protected long transmitDropped;
-    protected long receiveErrors;
-    protected long transmitErrors;
-    protected long receiveFrameErrors;
-    protected long receiveOverrunErrors;
-    protected long receiveCRCErrors;
-    protected long collisions;
-
-    /**
-     * @return the portNumber
-     */
-    @JsonSerialize(using=UShortSerializer.class)
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param portNumber the portNumber to set
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-    /**
-     * @return the receivePackets
-     */
-    public long getreceivePackets() {
-        return receivePackets;
-    }
-
-    /**
-     * @param receivePackets the receivePackets to set
-     */
-    public void setreceivePackets(long receivePackets) {
-        this.receivePackets = receivePackets;
-    }
-
-    /**
-     * @return the transmitPackets
-     */
-    public long getTransmitPackets() {
-        return transmitPackets;
-    }
-
-    /**
-     * @param transmitPackets the transmitPackets to set
-     */
-    public void setTransmitPackets(long transmitPackets) {
-        this.transmitPackets = transmitPackets;
-    }
-
-    /**
-     * @return the receiveBytes
-     */
-    public long getReceiveBytes() {
-        return receiveBytes;
-    }
-
-    /**
-     * @param receiveBytes the receiveBytes to set
-     */
-    public void setReceiveBytes(long receiveBytes) {
-        this.receiveBytes = receiveBytes;
-    }
-
-    /**
-     * @return the transmitBytes
-     */
-    public long getTransmitBytes() {
-        return transmitBytes;
-    }
-
-    /**
-     * @param transmitBytes the transmitBytes to set
-     */
-    public void setTransmitBytes(long transmitBytes) {
-        this.transmitBytes = transmitBytes;
-    }
-
-    /**
-     * @return the receiveDropped
-     */
-    public long getReceiveDropped() {
-        return receiveDropped;
-    }
-
-    /**
-     * @param receiveDropped the receiveDropped to set
-     */
-    public void setReceiveDropped(long receiveDropped) {
-        this.receiveDropped = receiveDropped;
-    }
-
-    /**
-     * @return the transmitDropped
-     */
-    public long getTransmitDropped() {
-        return transmitDropped;
-    }
-
-    /**
-     * @param transmitDropped the transmitDropped to set
-     */
-    public void setTransmitDropped(long transmitDropped) {
-        this.transmitDropped = transmitDropped;
-    }
-
-    /**
-     * @return the receiveErrors
-     */
-    public long getreceiveErrors() {
-        return receiveErrors;
-    }
-
-    /**
-     * @param receiveErrors the receiveErrors to set
-     */
-    public void setreceiveErrors(long receiveErrors) {
-        this.receiveErrors = receiveErrors;
-    }
-
-    /**
-     * @return the transmitErrors
-     */
-    public long getTransmitErrors() {
-        return transmitErrors;
-    }
-
-    /**
-     * @param transmitErrors the transmitErrors to set
-     */
-    public void setTransmitErrors(long transmitErrors) {
-        this.transmitErrors = transmitErrors;
-    }
-
-    /**
-     * @return the receiveFrameErrors
-     */
-    public long getReceiveFrameErrors() {
-        return receiveFrameErrors;
-    }
-
-    /**
-     * @param receiveFrameErrors the receiveFrameErrors to set
-     */
-    public void setReceiveFrameErrors(long receiveFrameErrors) {
-        this.receiveFrameErrors = receiveFrameErrors;
-    }
-
-    /**
-     * @return the receiveOverrunErrors
-     */
-    public long getReceiveOverrunErrors() {
-        return receiveOverrunErrors;
-    }
-
-    /**
-     * @param receiveOverrunErrors the receiveOverrunErrors to set
-     */
-    public void setReceiveOverrunErrors(long receiveOverrunErrors) {
-        this.receiveOverrunErrors = receiveOverrunErrors;
-    }
-
-    /**
-     * @return the receiveCRCErrors
-     */
-    public long getReceiveCRCErrors() {
-        return receiveCRCErrors;
-    }
-
-    /**
-     * @param receiveCRCErrors the receiveCRCErrors to set
-     */
-    public void setReceiveCRCErrors(long receiveCRCErrors) {
-        this.receiveCRCErrors = receiveCRCErrors;
-    }
-
-    /**
-     * @return the collisions
-     */
-    public long getCollisions() {
-        return collisions;
-    }
-
-    /**
-     * @param collisions the collisions to set
-     */
-    public void setCollisions(long collisions) {
-        this.collisions = collisions;
-    }
-
-    @Override
-    @JsonIgnore
-    public int getLength() {
-        return 104;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.portNumber = data.readShort();
-        data.readShort(); // pad
-        data.readInt(); // pad
-        this.receivePackets = data.readLong();
-        this.transmitPackets = data.readLong();
-        this.receiveBytes = data.readLong();
-        this.transmitBytes = data.readLong();
-        this.receiveDropped = data.readLong();
-        this.transmitDropped = data.readLong();
-        this.receiveErrors = data.readLong();
-        this.transmitErrors = data.readLong();
-        this.receiveFrameErrors = data.readLong();
-        this.receiveOverrunErrors = data.readLong();
-        this.receiveCRCErrors = data.readLong();
-        this.collisions = data.readLong();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeShort(this.portNumber);
-        data.writeShort((short) 0); // pad
-        data.writeInt(0); // pad
-        data.writeLong(this.receivePackets);
-        data.writeLong(this.transmitPackets);
-        data.writeLong(this.receiveBytes);
-        data.writeLong(this.transmitBytes);
-        data.writeLong(this.receiveDropped);
-        data.writeLong(this.transmitDropped);
-        data.writeLong(this.receiveErrors);
-        data.writeLong(this.transmitErrors);
-        data.writeLong(this.receiveFrameErrors);
-        data.writeLong(this.receiveOverrunErrors);
-        data.writeLong(this.receiveCRCErrors);
-        data.writeLong(this.collisions);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 431;
-        int result = 1;
-        result = prime * result + (int) (collisions ^ (collisions >>> 32));
-        result = prime * result + portNumber;
-        result = prime * result
-                + (int) (receivePackets ^ (receivePackets >>> 32));
-        result = prime * result + (int) (receiveBytes ^ (receiveBytes >>> 32));
-        result = prime * result
-                + (int) (receiveCRCErrors ^ (receiveCRCErrors >>> 32));
-        result = prime * result
-                + (int) (receiveDropped ^ (receiveDropped >>> 32));
-        result = prime * result
-                + (int) (receiveFrameErrors ^ (receiveFrameErrors >>> 32));
-        result = prime * result
-                + (int) (receiveOverrunErrors ^ (receiveOverrunErrors >>> 32));
-        result = prime * result
-                + (int) (receiveErrors ^ (receiveErrors >>> 32));
-        result = prime * result
-                + (int) (transmitBytes ^ (transmitBytes >>> 32));
-        result = prime * result
-                + (int) (transmitDropped ^ (transmitDropped >>> 32));
-        result = prime * result
-                + (int) (transmitErrors ^ (transmitErrors >>> 32));
-        result = prime * result
-                + (int) (transmitPackets ^ (transmitPackets >>> 32));
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFPortStatisticsReply)) {
-            return false;
-        }
-        OFPortStatisticsReply other = (OFPortStatisticsReply) obj;
-        if (collisions != other.collisions) {
-            return false;
-        }
-        if (portNumber != other.portNumber) {
-            return false;
-        }
-        if (receivePackets != other.receivePackets) {
-            return false;
-        }
-        if (receiveBytes != other.receiveBytes) {
-            return false;
-        }
-        if (receiveCRCErrors != other.receiveCRCErrors) {
-            return false;
-        }
-        if (receiveDropped != other.receiveDropped) {
-            return false;
-        }
-        if (receiveFrameErrors != other.receiveFrameErrors) {
-            return false;
-        }
-        if (receiveOverrunErrors != other.receiveOverrunErrors) {
-            return false;
-        }
-        if (receiveErrors != other.receiveErrors) {
-            return false;
-        }
-        if (transmitBytes != other.transmitBytes) {
-            return false;
-        }
-        if (transmitDropped != other.transmitDropped) {
-            return false;
-        }
-        if (transmitErrors != other.transmitErrors) {
-            return false;
-        }
-        if (transmitPackets != other.transmitPackets) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java b/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java
deleted file mode 100644
index c07a895af..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_port_stats_request structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFPortStatisticsRequest implements OFStatistics {
-    protected short portNumber;
-
-    /**
-     * @return the portNumber
-     */
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param portNumber the portNumber to set
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-    @Override
-    public int getLength() {
-        return 8;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.portNumber = data.readShort();
-        data.readShort(); // pad
-        data.readInt(); // pad
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeShort(this.portNumber);
-        data.writeShort((short) 0); // pad
-        data.writeInt(0); // pad
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 433;
-        int result = 1;
-        result = prime * result + portNumber;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFPortStatisticsRequest)) {
-            return false;
-        }
-        OFPortStatisticsRequest other = (OFPortStatisticsRequest) obj;
-        if (portNumber != other.portNumber) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java b/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java
deleted file mode 100644
index 34a9e1820..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_queue_stats structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFQueueStatisticsReply implements OFStatistics {
-    protected short portNumber;
-    protected int queueId;
-    protected long transmitBytes;
-    protected long transmitPackets;
-    protected long transmitErrors;
-
-    /**
-     * @return the portNumber
-     */
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param portNumber the portNumber to set
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-    /**
-     * @return the queueId
-     */
-    public int getQueueId() {
-        return queueId;
-    }
-
-    /**
-     * @param queueId the queueId to set
-     */
-    public void setQueueId(int queueId) {
-        this.queueId = queueId;
-    }
-
-    /**
-     * @return the transmitBytes
-     */
-    public long getTransmitBytes() {
-        return transmitBytes;
-    }
-
-    /**
-     * @param transmitBytes the transmitBytes to set
-     */
-    public void setTransmitBytes(long transmitBytes) {
-        this.transmitBytes = transmitBytes;
-    }
-
-    /**
-     * @return the transmitPackets
-     */
-    public long getTransmitPackets() {
-        return transmitPackets;
-    }
-
-    /**
-     * @param transmitPackets the transmitPackets to set
-     */
-    public void setTransmitPackets(long transmitPackets) {
-        this.transmitPackets = transmitPackets;
-    }
-
-    /**
-     * @return the transmitErrors
-     */
-    public long getTransmitErrors() {
-        return transmitErrors;
-    }
-
-    /**
-     * @param transmitErrors the transmitErrors to set
-     */
-    public void setTransmitErrors(long transmitErrors) {
-        this.transmitErrors = transmitErrors;
-    }
-
-    @Override
-    @JsonIgnore
-    public int getLength() {
-        return 32;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.portNumber = data.readShort();
-        data.readShort(); // pad
-        this.queueId = data.readInt();
-        this.transmitBytes = data.readLong();
-        this.transmitPackets = data.readLong();
-        this.transmitErrors = data.readLong();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeShort(this.portNumber);
-        data.writeShort((short) 0); // pad
-        data.writeInt(this.queueId);
-        data.writeLong(this.transmitBytes);
-        data.writeLong(this.transmitPackets);
-        data.writeLong(this.transmitErrors);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 439;
-        int result = 1;
-        result = prime * result + portNumber;
-        result = prime * result + queueId;
-        result = prime * result
-                + (int) (transmitBytes ^ (transmitBytes >>> 32));
-        result = prime * result
-                + (int) (transmitErrors ^ (transmitErrors >>> 32));
-        result = prime * result
-                + (int) (transmitPackets ^ (transmitPackets >>> 32));
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFQueueStatisticsReply)) {
-            return false;
-        }
-        OFQueueStatisticsReply other = (OFQueueStatisticsReply) obj;
-        if (portNumber != other.portNumber) {
-            return false;
-        }
-        if (queueId != other.queueId) {
-            return false;
-        }
-        if (transmitBytes != other.transmitBytes) {
-            return false;
-        }
-        if (transmitErrors != other.transmitErrors) {
-            return false;
-        }
-        if (transmitPackets != other.transmitPackets) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java b/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java
deleted file mode 100644
index 33314539f..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Represents an ofp_queue_stats_request structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFQueueStatisticsRequest implements OFStatistics {
-    protected short portNumber;
-    protected int queueId;
-
-    /**
-     * @return the portNumber
-     */
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param portNumber the portNumber to set
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-    /**
-     * @return the queueId
-     */
-    public int getQueueId() {
-        return queueId;
-    }
-
-    /**
-     * @param queueId the queueId to set
-     */
-    public void setQueueId(int queueId) {
-        this.queueId = queueId;
-    }
-
-    @Override
-    public int getLength() {
-        return 8;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.portNumber = data.readShort();
-        data.readShort(); // pad
-        this.queueId = data.readInt();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeShort(this.portNumber);
-        data.writeShort((short) 0); // pad
-        data.writeInt(this.queueId);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 443;
-        int result = 1;
-        result = prime * result + portNumber;
-        result = prime * result + queueId;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFQueueStatisticsRequest)) {
-            return false;
-        }
-        OFQueueStatisticsRequest other = (OFQueueStatisticsRequest) obj;
-        if (portNumber != other.portNumber) {
-            return false;
-        }
-        if (queueId != other.queueId) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFStatistics.java b/src/main/java/org/openflow/protocol/statistics/OFStatistics.java
deleted file mode 100644
index 5e8f4dd3f..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFStatistics.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * The base class for all OpenFlow statistics.
- *
- * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 11, 2010
- */
-public interface OFStatistics {
-    /**
-     * Returns the wire length of this message in bytes
-     * @return the length
-     */
-    public int getLength();
-
-    /**
-     * Read this message off the wire from the specified ByteBuffer
-     * @param data
-     */
-    public void readFrom(ChannelBuffer data);
-
-    /**
-     * Write this message's binary format to the specified ByteBuffer
-     * @param data
-     */
-    public void writeTo(ChannelBuffer data);
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java b/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java
deleted file mode 100644
index f2b9e3015..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-import java.lang.reflect.Constructor;
-
-import org.openflow.protocol.Instantiable;
-import org.openflow.protocol.OFType;
-
-public enum OFStatisticsType {
-    DESC        (0, OFDescriptionStatistics.class, OFDescriptionStatistics.class,
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFDescriptionStatistics();
-                        }
-                    },
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFDescriptionStatistics();
-                        }
-                    }),
-    FLOW       (1, OFFlowStatisticsRequest.class, OFFlowStatisticsReply.class,
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFFlowStatisticsRequest();
-                        }
-                    },
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFFlowStatisticsReply();
-                        }
-                    }),
-    AGGREGATE  (2, OFAggregateStatisticsRequest.class, OFAggregateStatisticsReply.class,
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFAggregateStatisticsRequest();
-                        }
-                    },
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFAggregateStatisticsReply();
-                        }
-                    }),
-    TABLE      (3, OFTableStatistics.class, OFTableStatistics.class,
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFTableStatistics();
-                        }
-                    },
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFTableStatistics();
-                        }
-                    }),
-    PORT       (4, OFPortStatisticsRequest.class, OFPortStatisticsReply.class,
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFPortStatisticsRequest();
-                        }
-                    },
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFPortStatisticsReply();
-                        }
-                    }),
-    QUEUE      (5, OFQueueStatisticsRequest.class, OFQueueStatisticsReply.class,
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFQueueStatisticsRequest();
-                        }
-                    },
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFQueueStatisticsReply();
-                        }
-                    }),
-    VENDOR     (0xffff, OFVendorStatistics.class, OFVendorStatistics.class,
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFVendorStatistics();
-                        }
-                    },
-                    new Instantiable<OFStatistics>() {
-                        @Override
-                        public OFStatistics instantiate() {
-                            return new OFVendorStatistics();
-                        }
-                    });
-
-    static OFStatisticsType[] requestMapping;
-    static OFStatisticsType[] replyMapping;
-
-    protected Class<? extends OFStatistics> requestClass;
-    protected Constructor<? extends OFStatistics> requestConstructor;
-    protected Instantiable<OFStatistics> requestInstantiable;
-    protected Class<? extends OFStatistics> replyClass;
-    protected Constructor<? extends OFStatistics> replyConstructor;
-    protected Instantiable<OFStatistics> replyInstantiable;
-    protected short type;
-
-    /**
-     * Store some information about the OpenFlow Statistic type, including wire
-     * protocol type number, and derived class
-     *
-     * @param type Wire protocol number associated with this OFStatisticsType
-     * @param requestClass The Statistics Java class to return when the
-     *                     containing OFType is STATS_REQUEST
-     * @param replyClass   The Statistics Java class to return when the
-     *                     containing OFType is STATS_REPLY
-     */
-    OFStatisticsType(int type, Class<? extends OFStatistics> requestClass,
-            Class<? extends OFStatistics> replyClass,
-            Instantiable<OFStatistics> requestInstantiable,
-            Instantiable<OFStatistics> replyInstantiable) {
-        this.type = (short) type;
-        this.requestClass = requestClass;
-        try {
-            this.requestConstructor = requestClass.getConstructor(new Class[]{});
-        } catch (Exception e) {
-            throw new RuntimeException(
-                    "Failure getting constructor for class: " + requestClass, e);
-        }
-
-        this.replyClass = replyClass;
-        try {
-            this.replyConstructor = replyClass.getConstructor(new Class[]{});
-        } catch (Exception e) {
-            throw new RuntimeException(
-                    "Failure getting constructor for class: " + replyClass, e);
-        }
-        this.requestInstantiable = requestInstantiable;
-        this.replyInstantiable = replyInstantiable;
-        OFStatisticsType.addMapping(this.type, OFType.STATS_REQUEST, this);
-        OFStatisticsType.addMapping(this.type, OFType.STATS_REPLY, this);
-    }
-
-    /**
-     * Adds a mapping from type value to OFStatisticsType enum
-     *
-     * @param i OpenFlow wire protocol type
-     * @param t type of containing OFMessage, only accepts STATS_REQUEST or
-     *          STATS_REPLY
-     * @param st type
-     */
-    static public void addMapping(short i, OFType t, OFStatisticsType st) {
-        if (i < 0)
-            i = (short) (16+i);
-        if (t == OFType.STATS_REQUEST) {
-            if (requestMapping == null)
-                requestMapping = new OFStatisticsType[16];
-            OFStatisticsType.requestMapping[i] = st;
-        } else if (t == OFType.STATS_REPLY){
-            if (replyMapping == null)
-                replyMapping = new OFStatisticsType[16];
-            OFStatisticsType.replyMapping[i] = st;
-        } else {
-            throw new RuntimeException(t.toString() + " is an invalid OFType");
-        }
-    }
-
-    /**
-     * Remove a mapping from type value to OFStatisticsType enum
-     *
-     * @param i OpenFlow wire protocol type
-     * @param t type of containing OFMessage, only accepts STATS_REQUEST or
-     *          STATS_REPLY
-     */
-    static public void removeMapping(short i, OFType t) {
-        if (i < 0)
-            i = (short) (16+i);
-        if (t == OFType.STATS_REQUEST) {
-            requestMapping[i] = null;
-        } else if (t == OFType.STATS_REPLY){
-            replyMapping[i] = null;
-        } else {
-            throw new RuntimeException(t.toString() + " is an invalid OFType");
-        }
-    }
-
-    /**
-     * Given a wire protocol OpenFlow type number, return the OFStatisticsType
-     * associated with it
-     *
-     * @param i wire protocol number
-     * @param t type of containing OFMessage, only accepts STATS_REQUEST or
-     *          STATS_REPLY
-     * @return OFStatisticsType enum type
-     */
-    static public OFStatisticsType valueOf(short i, OFType t) {
-        if (i < 0)
-            i = (short) (16+i);
-        if (t == OFType.STATS_REQUEST) {
-            return requestMapping[i];
-        } else if (t == OFType.STATS_REPLY){
-            return replyMapping[i];
-        } else {
-            throw new RuntimeException(t.toString() + " is an invalid OFType");
-        }
-    }
-
-    /**
-     * @return Returns the wire protocol value corresponding to this
-     * OFStatisticsType
-     */
-    public short getTypeValue() {
-        return this.type;
-    }
-
-    /**
-     * @param t type of containing OFMessage, only accepts STATS_REQUEST or
-     *          STATS_REPLY
-     * @return return the OFMessage subclass corresponding to this
-     *                OFStatisticsType
-     */
-    public Class<? extends OFStatistics> toClass(OFType t) {
-        if (t == OFType.STATS_REQUEST) {
-            return requestClass;
-        } else if (t == OFType.STATS_REPLY){
-            return replyClass;
-        } else {
-            throw new RuntimeException(t.toString() + " is an invalid OFType");
-        }
-    }
-
-    /**
-     * Returns the no-argument Constructor of the implementation class for
-     * this OFStatisticsType, either request or reply based on the supplied
-     * OFType
-     *
-     * @param t
-     * @return
-     */
-    public Constructor<? extends OFStatistics> getConstructor(OFType t) {
-        if (t == OFType.STATS_REQUEST) {
-            return requestConstructor;
-        } else if (t == OFType.STATS_REPLY) {
-            return replyConstructor;
-        } else {
-            throw new RuntimeException(t.toString() + " is an invalid OFType");
-        }
-    }
-
-    /**
-     * @return the requestInstantiable
-     */
-    public Instantiable<OFStatistics> getRequestInstantiable() {
-        return requestInstantiable;
-    }
-
-    /**
-     * @param requestInstantiable the requestInstantiable to set
-     */
-    public void setRequestInstantiable(
-            Instantiable<OFStatistics> requestInstantiable) {
-        this.requestInstantiable = requestInstantiable;
-    }
-
-    /**
-     * @return the replyInstantiable
-     */
-    public Instantiable<OFStatistics> getReplyInstantiable() {
-        return replyInstantiable;
-    }
-
-    /**
-     * @param replyInstantiable the replyInstantiable to set
-     */
-    public void setReplyInstantiable(Instantiable<OFStatistics> replyInstantiable) {
-        this.replyInstantiable = replyInstantiable;
-    }
-
-    /**
-     * Returns a new instance of the implementation class for
-     * this OFStatisticsType, either request or reply based on the supplied
-     * OFType
-     *
-     * @param t
-     * @return
-     */
-    public OFStatistics newInstance(OFType t) {
-        if (t == OFType.STATS_REQUEST) {
-            return requestInstantiable.instantiate();
-        } else if (t == OFType.STATS_REPLY) {
-            return replyInstantiable.instantiate();
-        } else {
-            throw new RuntimeException(t.toString() + " is an invalid OFType");
-        }
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java b/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java
deleted file mode 100644
index 9e6d34e10..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.util.StringByteSerializer;
-
-/**
- * Represents an ofp_table_stats structure
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFTableStatistics implements OFStatistics {
-    public static int MAX_TABLE_NAME_LEN = 32;
-
-    protected byte tableId;
-    protected String name;
-    protected int wildcards;
-    protected int maximumEntries;
-    protected int activeCount;
-    protected long lookupCount;
-    protected long matchedCount;
-
-    /**
-     * @return the tableId
-     */
-    public byte getTableId() {
-        return tableId;
-    }
-
-    /**
-     * @param tableId the tableId to set
-     */
-    public void setTableId(byte tableId) {
-        this.tableId = tableId;
-    }
-
-    /**
-     * @return the name
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * @param name the name to set
-     */
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    /**
-     * @return the wildcards
-     */
-    public int getWildcards() {
-        return wildcards;
-    }
-
-    /**
-     * @param wildcards the wildcards to set
-     */
-    public void setWildcards(int wildcards) {
-        this.wildcards = wildcards;
-    }
-
-    /**
-     * @return the maximumEntries
-     */
-    public int getMaximumEntries() {
-        return maximumEntries;
-    }
-
-    /**
-     * @param maximumEntries the maximumEntries to set
-     */
-    public void setMaximumEntries(int maximumEntries) {
-        this.maximumEntries = maximumEntries;
-    }
-
-    /**
-     * @return the activeCount
-     */
-    public int getActiveCount() {
-        return activeCount;
-    }
-
-    /**
-     * @param activeCount the activeCount to set
-     */
-    public void setActiveCount(int activeCount) {
-        this.activeCount = activeCount;
-    }
-
-    /**
-     * @return the lookupCount
-     */
-    public long getLookupCount() {
-        return lookupCount;
-    }
-
-    /**
-     * @param lookupCount the lookupCount to set
-     */
-    public void setLookupCount(long lookupCount) {
-        this.lookupCount = lookupCount;
-    }
-
-    /**
-     * @return the matchedCount
-     */
-    public long getMatchedCount() {
-        return matchedCount;
-    }
-
-    /**
-     * @param matchedCount the matchedCount to set
-     */
-    public void setMatchedCount(long matchedCount) {
-        this.matchedCount = matchedCount;
-    }
-
-    @Override
-    public int getLength() {
-        return 64;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.tableId = data.readByte();
-        data.readByte(); // pad
-        data.readByte(); // pad
-        data.readByte(); // pad
-        this.name = StringByteSerializer.readFrom(data, MAX_TABLE_NAME_LEN);
-        this.wildcards = data.readInt();
-        this.maximumEntries = data.readInt();
-        this.activeCount = data.readInt();
-        this.lookupCount = data.readLong();
-        this.matchedCount = data.readLong();
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeByte(this.tableId);
-        data.writeByte((byte) 0); // pad
-        data.writeByte((byte) 0); // pad
-        data.writeByte((byte) 0); // pad
-        StringByteSerializer.writeTo(data, MAX_TABLE_NAME_LEN, this.name);
-        data.writeInt(this.wildcards);
-        data.writeInt(this.maximumEntries);
-        data.writeInt(this.activeCount);
-        data.writeLong(this.lookupCount);
-        data.writeLong(this.matchedCount);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 449;
-        int result = 1;
-        result = prime * result + activeCount;
-        result = prime * result + (int) (lookupCount ^ (lookupCount >>> 32));
-        result = prime * result + (int) (matchedCount ^ (matchedCount >>> 32));
-        result = prime * result + maximumEntries;
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result + tableId;
-        result = prime * result + wildcards;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFTableStatistics)) {
-            return false;
-        }
-        OFTableStatistics other = (OFTableStatistics) obj;
-        if (activeCount != other.activeCount) {
-            return false;
-        }
-        if (lookupCount != other.lookupCount) {
-            return false;
-        }
-        if (matchedCount != other.matchedCount) {
-            return false;
-        }
-        if (maximumEntries != other.maximumEntries) {
-            return false;
-        }
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
-        if (tableId != other.tableId) {
-            return false;
-        }
-        if (wildcards != other.wildcards) {
-            return false;
-        }
-        return true;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java b/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java
deleted file mode 100644
index 0257a6aab..000000000
--- a/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol.statistics;
-
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * The base class for vendor implemented statistics
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class OFVendorStatistics implements OFStatistics {
-    protected int vendor;
-    protected byte[] body;
-
-    // non-message fields
-    protected int length = 0;
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        this.vendor = data.readInt();
-        if (body == null)
-            body = new byte[length - 4];
-        data.readBytes(body);
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeInt(this.vendor);
-        if (body != null)
-            data.writeBytes(body);
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 457;
-        int result = 1;
-        result = prime * result + vendor;
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof OFVendorStatistics)) {
-            return false;
-        }
-        OFVendorStatistics other = (OFVendorStatistics) obj;
-        if (vendor != other.vendor) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public int getLength() {
-        return length;
-    }
-
-    public void setLength(int length) {
-        this.length = length;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java b/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java
deleted file mode 100644
index 1f0e14b2d..000000000
--- a/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.protocol.vendor;
-
-import org.openflow.protocol.Instantiable;
-
-/**
- * Subclass of OFVendorDataType that works with any vendor data format that
- * begins with a integral value to indicate the format of the remaining data.
- * It maps from the per-vendor-id integral data type code to the object
- * used to instantiate the class associated with that vendor data type.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public class OFBasicVendorDataType extends OFVendorDataType {
-    
-    /**
-     * The data type value at the beginning of the vendor data.
-     */
-    protected long type;
-    
-    /**
-     * Construct an empty (i.e. no specified data type value) vendor data type.
-     */
-    public OFBasicVendorDataType() {
-        super();
-        this.type = 0;
-    }
-    
-    /**
-     * Store some information about the vendor data type, including wire protocol
-     * type number, derived class and instantiator.
-     *
-     * @param type Wire protocol number associated with this vendor data type
-     * @param instantiator An Instantiator<OFVendorData> implementation that
-     *              creates an instance of an appropriate subclass of OFVendorData.
-     */
-    public OFBasicVendorDataType(long type, Instantiable<OFVendorData> instantiator) {
-        super(instantiator);
-        this.type = type;
-    }
-
-    /**
-     * @return Returns the wire protocol value corresponding to this OFVendorDataType
-     */
-    public long getTypeValue() {
-        return this.type;
-    }
-    
-    /**
-     * @param type the wire protocol value for this data type
-     */
-    public void setTypeValue(long type) {
-        this.type = type;
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java b/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java
deleted file mode 100644
index 5f789dc3f..000000000
--- a/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.protocol.vendor;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.Instantiable;
-
-/**
- * Basic subclass of OFVendorId that works with any vendor data format where
- * the data begins with an integral data type value.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public class OFBasicVendorId extends OFVendorId {
-    
-    /**
-     * The size of the data type value at the beginning of all vendor
-     * data associated with this vendor id. The data type size must be
-     * either 1, 2, 4 or 8.
-     */
-    protected int dataTypeSize;
-    
-    /**
-     * Map of the vendor data types that have been registered for this
-     * vendor id.
-     */
-    protected Map<Long, OFBasicVendorDataType> dataTypeMap =
-            new HashMap<Long, OFBasicVendorDataType>();
-    
-    /**
-     * Construct an OFVendorId that where the vendor data begins
-     * with a data type value whose size is dataTypeSize.
-     * @param id the id of the vendor, typically the OUI of a vendor
-     *     prefixed with 0.
-     * @param dataTypeSize the size of the integral data type value
-     *     at the beginning of the vendor data. The value must be the
-     *     size of an integeral data type (i.e. either 1,2,4 or 8).
-     */
-    public OFBasicVendorId(int id, int dataTypeSize) {
-        super(id);
-        assert (dataTypeSize == 1) || (dataTypeSize == 2) ||
-               (dataTypeSize == 4) || (dataTypeSize == 8);
-        this.dataTypeSize = dataTypeSize;
-    }
-
-    /**
-     * Get the size of the data type value at the beginning of the vendor
-     * data. OFBasicVendorId assumes that this value is common across all of
-     * the vendor data formats associated with a given vendor id.
-     * @return
-     */
-    public int getDataTypeSize() {
-        return dataTypeSize;
-    }
-    
-    /**
-     * Register a vendor data type with this vendor id.
-     * @param vendorDataType
-     */
-    public void registerVendorDataType(OFBasicVendorDataType vendorDataType) {
-        dataTypeMap.put(vendorDataType.getTypeValue(), vendorDataType);
-    }
-    
-    /**
-     * Lookup the OFVendorDataType instance that has been registered with
-     * this vendor id.
-     * 
-     * @param vendorDataType the integer code that was parsed from the 
-     * @return
-     */
-    public OFVendorDataType lookupVendorDataType(int vendorDataType) {
-        return dataTypeMap.get(Long.valueOf(vendorDataType));
-    }
-
-    /**
-     * This function parses enough of the data from the buffer to be able
-     * to determine the appropriate OFVendorDataType for the data. It is meant
-     * to be a reasonably generic implementation that will work for most
-     * formats of vendor extensions. If the vendor data doesn't fit the
-     * assumptions listed below, then this method will need to be overridden
-     * to implement custom parsing.
-     * 
-     * This implementation assumes that the vendor data begins with a data
-     * type code that is used to distinguish different formats of vendor
-     * data associated with a particular vendor ID.
-     * The exact format of the data is vendor-defined, so we don't know how
-     * how big the code is (or really even if there is a code). This code
-     * assumes that the common case will be that the data does include
-     * an initial type code (i.e. so that the vendor can have multiple
-     * message/data types) and that the size is either 1, 2 or 4 bytes.
-     * The size of the initial type code is configured by the subclass of
-     * OFVendorId.
-     * 
-     * @param data the channel buffer containing the vendor data.
-     * @param length the length to the end of the enclosing message
-     * @return the OFVendorDataType that can be used to instantiate the
-     *         appropriate subclass of OFVendorData.
-     */
-    public OFVendorDataType parseVendorDataType(ChannelBuffer data, int length) {
-        OFVendorDataType vendorDataType = null;
-        
-        // Parse out the type code from the vendor data.
-        long dataTypeValue = 0;
-        if ((length == 0) || (length >= dataTypeSize)) {
-            switch (dataTypeSize) {
-                case 1:
-                    dataTypeValue = data.readByte();
-                    break;
-                case 2:
-                    dataTypeValue = data.readShort();
-                    break;
-                case 4:
-                    dataTypeValue = data.readInt();
-                    break;
-                case 8:
-                    dataTypeValue = data.readLong();
-                    break;
-                default:
-                    // This would be indicative of a coding error where the
-                    // dataTypeSize was specified incorrectly. This should have been
-                    // caught in the constructor for OFVendorId.
-                    assert false;
-            }
-            
-            vendorDataType = dataTypeMap.get(dataTypeValue);
-        }
-        
-        // If we weren't able to parse/map the data to a known OFVendorDataType,
-        // then map it to a generic vendor data type.
-        if (vendorDataType == null) {
-            vendorDataType = new OFBasicVendorDataType(dataTypeValue,
-                new Instantiable<OFVendorData>() {
-                    @Override
-                    public OFVendorData instantiate() {
-                        return new OFByteArrayVendorData();
-                    }
-                }
-            );
-        }
-        
-        return vendorDataType;
-    }
-
-}
diff --git a/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java b/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java
deleted file mode 100644
index 08fa00317..000000000
--- a/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.protocol.vendor;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Basic implementation of OFVendorData that just treats the data as a
- * byte array. This is used if there's an OFVendor message where there's
- * no registered OFVendorId or no specific OFVendorDataType that can be
- * determined from the data.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public class OFByteArrayVendorData implements OFVendorData {
-
-    protected byte[] bytes;
-    
-    /**
-     * Construct vendor data with an empty byte array.
-     */
-    public OFByteArrayVendorData() {
-    }
-    
-    /**
-     * Construct vendor data with the specified byte array.
-     * @param bytes
-     */
-    public OFByteArrayVendorData(byte[] bytes) {
-        this.bytes = bytes;
-    }
-    
-    /**
-     * Get the associated byte array for this vendor data.
-     * @return the byte array containing the raw vendor data.
-     */
-    public byte[] getBytes() {
-        return bytes;
-    }
-    
-    /**
-     * Set the byte array for the vendor data.
-     * @param bytes the raw byte array containing the vendor data.
-     */
-    public void setBytes(byte[] bytes) {
-        this.bytes = bytes;
-    }
-    
-    /**
-     * Get the length of the vendor data. In this case it's just then length
-     * of the underlying byte array.
-     * @return the length of the vendor data
-     */
-    @Override
-    public int getLength() {
-        return (bytes != null) ? bytes.length : 0;
-    }
-
-    /**
-     * Read the vendor data from the ChannelBuffer into the byte array.
-     * @param data the channel buffer from which we're deserializing
-     * @param length the length to the end of the enclosing message
-     */
-    @Override
-    public void readFrom(ChannelBuffer data, int length) {
-        bytes = new byte[length];
-        data.readBytes(bytes);
-    }
-
-    /**
-     * Write the vendor data bytes to the ChannelBuffer
-     * @param data the channel buffer to which we're serializing
-     */
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        if (bytes != null)
-            data.writeBytes(bytes);
-    }
-}
diff --git a/src/main/java/org/openflow/protocol/vendor/OFVendorData.java b/src/main/java/org/openflow/protocol/vendor/OFVendorData.java
deleted file mode 100644
index 6dfb4e6cb..000000000
--- a/src/main/java/org/openflow/protocol/vendor/OFVendorData.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.protocol.vendor;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * The base class for all vendor data.
- *
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public interface OFVendorData {
-    /**
-     * @return length of the data
-     */
-    public int getLength();
-    
-    /**
-     * Read the vendor data from the specified ChannelBuffer
-     * @param data
-     */
-    public void readFrom(ChannelBuffer data, int length);
-
-    /**
-     * Write the vendor data to the specified ChannelBuffer
-     * @param data
-     */
-    public void writeTo(ChannelBuffer data);
-}
diff --git a/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java b/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java
deleted file mode 100644
index ecae48239..000000000
--- a/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.protocol.vendor;
-
-import org.openflow.protocol.Instantiable;
-
-/**
- * Class that represents a specific vendor data type format in an
- * OFVendor message. Typically the vendor data will begin with an integer
- * code that determines the format of the rest of the data, but this
- * class does not assume that. It's basically just a holder for an
- * instantiator of the appropriate subclass of OFVendorData.
- *
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public class OFVendorDataType {
-
-    /**
-     * Object that instantiates the subclass of OFVendorData 
-     * associated with this data type.
-     */
-    protected Instantiable<OFVendorData> instantiable;
-
-    /**
-     * Construct an empty vendor data type.
-     */
-    public OFVendorDataType() {
-        super();
-    }
-
-    /**
-     * Construct a vendor data type with the specified instantiable.
-     * @param instantiable object that creates the subclass of OFVendorData
-     *     associated with this data type.
-     */
-    public OFVendorDataType(Instantiable<OFVendorData> instantiable) {
-        this.instantiable = instantiable;
-    }
-    
-    /**
-     * Returns a new instance of a subclass of OFVendorData associated with
-     * this OFVendorDataType.
-     * 
-     * @return the new object
-     */
-    public OFVendorData newInstance() {
-        return instantiable.instantiate();
-    }
-
-    /**
-     * @return the instantiable
-     */
-    public Instantiable<OFVendorData> getInstantiable() {
-        return instantiable;
-    }
-
-    /**
-     * @param instantiable the instantiable to set
-     */
-    public void setInstantiable(Instantiable<OFVendorData> instantiable) {
-        this.instantiable = instantiable;
-    }
-
-}
diff --git a/src/main/java/org/openflow/protocol/vendor/OFVendorId.java b/src/main/java/org/openflow/protocol/vendor/OFVendorId.java
deleted file mode 100644
index f0af8a763..000000000
--- a/src/main/java/org/openflow/protocol/vendor/OFVendorId.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.protocol.vendor;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Base class for the vendor ID corresponding to vendor extensions from a
- * given vendor. It is responsible for knowing how to parse out some sort of
- * data type value from the vendor data in an OFVendor message so that we can
- * dispatch to the different subclasses of OFVendorData corresponding to the
- * different formats of data for the vendor extensions.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public abstract class OFVendorId {
-    static Map<Integer, OFVendorId> mapping = new HashMap<Integer, OFVendorId>();
-
-    /**
-     * The vendor id value, typically the OUI of the vendor prefixed with 0.
-     */
-    protected int id;
-    
-    /**
-     * Register a new vendor id.
-     * @param vendorId the vendor id to register
-     */
-    public static void registerVendorId(OFVendorId vendorId) {
-        mapping.put(vendorId.getId(), vendorId);
-    }
-    
-    /**
-     * Lookup the OFVendorId instance corresponding to the given id value.
-     * @param id the integer vendor id value
-     * @return the corresponding OFVendorId that's been registered for the
-     *     given value, or null if there id has not been registered.
-     */
-    public static OFVendorId lookupVendorId(int id) {
-        return mapping.get(id);
-    }
-    
-    /**
-     * Create an OFVendorId with the give vendor id value
-     * @param id
-     */
-    public OFVendorId(int id) {
-        this.id = id;
-    }
-    
-    /**
-     * @return the vendor id value
-     */
-    public int getId() {
-        return id;
-    }
-    
-    /**
-     * This function parses enough of the data from the channel buffer to be
-     * able to determine the appropriate OFVendorDataType for the data.
-     * 
-     * @param data the channel buffer containing the vendor data.
-     * @param length the length to the end of the enclosing message
-     * @return the OFVendorDataType that can be used to instantiate the
-     *         appropriate subclass of OFVendorData.
-     */
-    public abstract OFVendorDataType parseVendorDataType(ChannelBuffer data, int length);
-}
diff --git a/src/main/java/org/openflow/util/HexString.java b/src/main/java/org/openflow/util/HexString.java
deleted file mode 100644
index b5628242d..000000000
--- a/src/main/java/org/openflow/util/HexString.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import java.math.BigInteger;
-
-public class HexString {
-    /**
-     * Convert a string of bytes to a ':' separated hex string
-     * @param bytes
-     * @return "0f:ca:fe:de:ad:be:ef"
-     */
-    public static String toHexString(byte[] bytes) {
-        if (bytes == null) return "";
-        int i;
-        String ret = "";
-        String tmp;
-        for(i=0; i< bytes.length; i++) {
-            if(i> 0)
-                ret += ":";
-            tmp = Integer.toHexString(U8.f(bytes[i]));
-            if (tmp.length() == 1)
-                ret += "0";
-            ret += tmp; 
-        }
-        return ret;
-    }
-    
-    public static String toHexString(long val, int padTo) {
-        char arr[] = Long.toHexString(val).toCharArray();
-        String ret = "";
-        // prepend the right number of leading zeros
-        int i = 0;
-        for (; i < (padTo * 2 - arr.length); i++) {
-            ret += "0";
-            if ((i % 2) != 0)
-                ret += ":";
-        }
-        for (int j = 0; j < arr.length; j++) {
-            ret += arr[j];
-            if ((((i + j) % 2) != 0) && (j < (arr.length - 1)))
-                ret += ":";
-        }
-        return ret;        
-    }
-   
-    public static String toHexString(long val) {
-        return toHexString(val, 8);
-    }
-    
-    
-    /**
-     * Convert a string of hex values into a string of bytes
-     * @param values "0f:ca:fe:de:ad:be:ef"
-     * @return [15, 5 ,2, 5, 17] 
-     * @throws NumberFormatException If the string can not be parsed
-     */ 
-    public static byte[] fromHexString(String values) throws NumberFormatException {
-        String[] octets = values.split(":");
-        byte[] ret = new byte[octets.length];
-        
-        for(int i = 0; i < octets.length; i++) {
-            if (octets[i].length() > 2)
-                throw new NumberFormatException("Invalid octet length");
-            ret[i] = Integer.valueOf(octets[i], 16).byteValue();
-        }
-        return ret;
-    }
-    
-    public static long toLong(String values) throws NumberFormatException {
-        // Long.parseLong() can't handle HexStrings with MSB set. Sigh. 
-        BigInteger bi = new BigInteger(values.replaceAll(":", ""),16);
-        if (bi.bitLength() > 64) 
-            throw new NumberFormatException("Input string too big to fit in long: " + values);
-        return bi.longValue();
-    }
-
-}
diff --git a/src/main/java/org/openflow/util/IProducer.java b/src/main/java/org/openflow/util/IProducer.java
deleted file mode 100644
index 52ae79a52..000000000
--- a/src/main/java/org/openflow/util/IProducer.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package org.openflow.util;
-
-public interface IProducer {
-
-    public void registerConsumer(Class<?> iface, Object anObj);
-
-    public void deregisterConsumer(Class<?> iface, Object anObj);
-
-}
diff --git a/src/main/java/org/openflow/util/LRULinkedHashMap.java b/src/main/java/org/openflow/util/LRULinkedHashMap.java
deleted file mode 100644
index 7f05381c2..000000000
--- a/src/main/java/org/openflow/util/LRULinkedHashMap.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import java.util.LinkedHashMap;
-
-public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {
-    private static final long serialVersionUID = -2964986094089626647L;
-    protected int maximumCapacity;
-
-    public LRULinkedHashMap(int initialCapacity, int maximumCapacity) {
-        super(initialCapacity, 0.75f, true);
-        this.maximumCapacity = maximumCapacity;
-    }
-
-    public LRULinkedHashMap(int maximumCapacity) {
-        super(16, 0.75f, true);
-        this.maximumCapacity = maximumCapacity;
-    }
-
-    @Override
-    protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
-        if (this.size() > maximumCapacity)
-            return true;
-        return false;
-    }
-}
diff --git a/src/main/java/org/openflow/util/ProducerConsumer.java b/src/main/java/org/openflow/util/ProducerConsumer.java
deleted file mode 100644
index f2244ef35..000000000
--- a/src/main/java/org/openflow/util/ProducerConsumer.java
+++ /dev/null
@@ -1,223 +0,0 @@
-package org.openflow.util;
-
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * The following implement a producer/consumer design pattern in which both
- * producers and consumers explicitly employ a centralized registration
- * mechanism, and java Interfaces are used as contracts.<br>
- */
-public class ProducerConsumer {
-
-    /*
-     * Class variables
-     */
-    protected static ProducerConsumer singleton;
-
-    /*
-     * Default constructor
-     */
-    protected ProducerConsumer() {
-        producerMap = new Hashtable<Class<?>, Set<IProducer>>();
-    }
-
-    /*
-     * Instance variables
-     */
-
-    // Interface/IProducer map
-    protected Map<Class<?>, Set<IProducer>> producerMap;
-
-    /*
-     * Protected methods
-     */
-
-    protected void _registerConsumer(Object consumer, Class<?>[] interfaces,
-                                     Set<Class<?>> iSet,
-                                     Set<Class<?>> iUniqueSet) {
-        // *...Process all interfaces...*/
-        for (Class<?> iface : interfaces) {
-
-            // *...Protect against repeated interfaces...*/
-            if (!iUniqueSet.contains(iface)) {
-                iUniqueSet.add(iface);
-
-                Set<IProducer> producers = producerMap.get(iface);
-
-                if (producers != null) {
-                    for (IProducer producer : producers)
-                        producer.registerConsumer(iface, consumer);
-                    iSet.add(iface);
-                }
-
-                // *...Recurse...*/
-                _registerConsumer(consumer, iface.getInterfaces(), iSet,
-                                  iUniqueSet);
-            }
-        }
-    }
-
-    protected void _registerConsumer(Object consumer, Class<?> clazz,
-                                     Set<Class<?>> iSet,
-                                     Set<Class<?>> iUniqueSet) {
-        if (clazz != null) {
-            // *...Process all interfaces...*/
-            _registerConsumer(consumer, clazz.getInterfaces(), iSet,
-                              iUniqueSet);
-
-            // *...Recurse the class hierarchy...*/
-            _registerConsumer(consumer, clazz.getSuperclass(), iSet,
-                              iUniqueSet);
-        }
-    }
-
-    protected int _deregisterConsumer(Object consumer,
-                                      Class<?>[] interfaces,
-                                      Set<Class<?>> iUniqueSet) {
-        int count = 0;
-
-        // *...Process all interfaces...*/
-        for (Class<?> iface : interfaces) {
-
-            // *...Protect against repeated interfaces...*/
-            if (!iUniqueSet.contains(iface)) {
-                iUniqueSet.add(iface);
-
-                Set<IProducer> producers = producerMap.get(iface);
-
-                if (producers != null) {
-                    for (IProducer producer : producers)
-                        producer.deregisterConsumer(iface, consumer);
-
-                    count++;
-                }
-
-                // *...Recurse...*/
-                count += _deregisterConsumer(consumer,
-                                             iface.getInterfaces(),
-                                             iUniqueSet);
-            }
-        }
-
-        return count;
-    }
-
-    protected int _deregisterConsumer(Object consumer, Class<?> clazz,
-                                      Set<Class<?>> iUniqueSet) {
-        int count = 0;
-
-        if (clazz != null) {
-            // *...Process all interfaces...*/
-            count += _deregisterConsumer(consumer, clazz.getInterfaces(),
-                                         iUniqueSet);
-
-            // *...Recurse the class hierarchy...*/
-            count += _deregisterConsumer(consumer, clazz.getSuperclass(),
-                                         iUniqueSet);
-        }
-
-        return count;
-    }
-
-    /*
-     * Singleton API
-     */
-
-    /**
-     * @return singleton ProducerConsumer
-     */
-    public static synchronized ProducerConsumer getSingleton() {
-        if (singleton == null) singleton = new ProducerConsumer();
-
-        return singleton;
-    }
-
-    /*
-     * Producer APIs
-     */
-
-    /**
-     * Producer registration
-     * 
-     * @param producer
-     *            object that implements IProducer
-     * @param iface
-     *            interface supported by the producer
-     * @return whether there was a previously registered producer, or true if
-     *         one or more the arguments were invalid
-     */
-    public boolean registerProducer(IProducer producer, Class<?> iface) {
-        if (producer != null && iface != null && iface.isInterface()) {
-            Set<IProducer> producers = producerMap.get(iface);
-
-            if (producers == null) {
-                producers = new HashSet<IProducer>();
-                producerMap.put(iface, producers);
-            }
-
-            return producers.add(producer);
-        } else
-            return true;
-    }
-
-    /**
-     * Producer deregistration
-     * 
-     * @param producer
-     *            object that implements IProducer
-     * @param iface
-     *            interface supported by the producer
-     * @return whether the interface/producer pair was removed, or false if one
-     *         or more the arguments were invalid
-     */
-    public boolean deregisterProducer(IProducer producer, Class<?> iface) {
-        if (producer != null && iface != null && iface.isInterface()) {
-            Set<IProducer> producers = producerMap.get(iface);
-
-            if (producers != null) return producers.remove(producer);
-        }
-
-        return false;
-    }
-
-    /*
-     * Consumer APIs
-     */
-
-    /**
-     * Consumer registration
-     * 
-     * @param consumer
-     *            object that implements producer-specific interfaces
-     * @return set of supported interfaces
-     */
-    public Set<Class<?>> registerConsumer(Object consumer) {
-        Set<Class<?>> iSet = new HashSet<Class<?>>();
-
-        if (consumer != null)
-                             _registerConsumer(consumer,
-                                               consumer.getClass(), iSet,
-                                               new HashSet<Class<?>>());
-
-        return iSet;
-    }
-
-    /**
-     * Consumer deregistration
-     * 
-     * @param consumer
-     *            object to deregister
-     * @return number of unregistered interfaces
-     */
-    public int deregisterConsumer(Object consumer) {
-        if (consumer != null)
-            return _deregisterConsumer(consumer, consumer.getClass(),
-                                       new HashSet<Class<?>>());
-        else
-            return 0;
-    }
-
-}
diff --git a/src/main/java/org/openflow/util/StringByteSerializer.java b/src/main/java/org/openflow/util/StringByteSerializer.java
deleted file mode 100644
index 9287fd20a..000000000
--- a/src/main/java/org/openflow/util/StringByteSerializer.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-public class StringByteSerializer {
-    public static String readFrom(ChannelBuffer data, int length) {
-        byte[] stringBytes = new byte[length];
-        data.readBytes(stringBytes);
-        // find the first index of 0
-        int index = 0;
-        for (byte b : stringBytes) {
-            if (0 == b)
-                break;
-            ++index;
-        }
-        return new String(Arrays.copyOf(stringBytes, index),
-                Charset.forName("ascii"));
-    }
-
-    public static void writeTo(ChannelBuffer data, int length, String value) {
-        try {
-            byte[] name = value.getBytes("ASCII");
-            if (name.length < length) {
-                data.writeBytes(name);
-                for (int i = name.length; i < length; ++i) {
-                    data.writeByte((byte) 0);
-                }
-            } else {
-                data.writeBytes(name, 0, length-1);
-                data.writeByte((byte) 0);
-            }
-        } catch (UnsupportedEncodingException e) {
-            throw new RuntimeException(e);
-        }
-
-    }
-}
diff --git a/src/main/java/org/openflow/util/U16.java b/src/main/java/org/openflow/util/U16.java
deleted file mode 100644
index 0d8917da5..000000000
--- a/src/main/java/org/openflow/util/U16.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-public class U16 {
-    public static int f(short i) {
-        return (int)i & 0xffff;
-    }
-
-    public static short t(int l) {
-        return (short) l;
-    }
-}
diff --git a/src/main/java/org/openflow/util/U32.java b/src/main/java/org/openflow/util/U32.java
deleted file mode 100644
index 3aab400eb..000000000
--- a/src/main/java/org/openflow/util/U32.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-public class U32 {
-    public static long f(int i) {
-        return (long)i & 0xffffffffL;
-    }
-
-    public static int t(long l) {
-        return (int) l;
-    }
-}
diff --git a/src/main/java/org/openflow/util/U64.java b/src/main/java/org/openflow/util/U64.java
deleted file mode 100644
index c6ae0f7b5..000000000
--- a/src/main/java/org/openflow/util/U64.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import java.math.BigInteger;
-
-public class U64 {
-    public static BigInteger f(long i) {
-        return new BigInteger(Long.toBinaryString(i), 2);
-    }
-
-    public static long t(BigInteger l) {
-        return l.longValue();
-    }
-}
diff --git a/src/main/java/org/openflow/util/U8.java b/src/main/java/org/openflow/util/U8.java
deleted file mode 100644
index 0b575ad24..000000000
--- a/src/main/java/org/openflow/util/U8.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-public class U8 {
-    public static short f(byte i) {
-        return (short) ((short)i & 0xff);
-    }
-
-    public static byte t(short l) {
-        return (byte) l;
-    }
-}
diff --git a/src/main/java/org/openflow/util/Unsigned.java b/src/main/java/org/openflow/util/Unsigned.java
deleted file mode 100644
index 0754a3f73..000000000
--- a/src/main/java/org/openflow/util/Unsigned.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-
-/*****
- * A util library class for dealing with the lack of unsigned datatypes in Java
- *
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-
-public class Unsigned {
-    /**
-     * Get an unsigned byte from the current position of the ByteBuffer
-     *
-     * @param bb ByteBuffer to get the byte from
-     * @return an unsigned byte contained in a short
-     */
-    public static short getUnsignedByte(ByteBuffer bb) {
-        return ((short) (bb.get() & (short) 0xff));
-    }
-
-    /**
-     * Get an unsigned byte from the specified offset in the ByteBuffer
-     *
-     * @param bb ByteBuffer to get the byte from
-     * @param offset the offset to get the byte from
-     * @return an unsigned byte contained in a short
-     */
-    public static short getUnsignedByte(ByteBuffer bb, int offset) {
-        return ((short) (bb.get(offset) & (short) 0xff));
-    }
-
-    /**
-     * Put an unsigned byte into the specified ByteBuffer at the current
-     * position
-     *
-     * @param bb ByteBuffer to put the byte into
-     * @param v the short containing the unsigned byte
-     */
-    public static void putUnsignedByte(ByteBuffer bb, short v) {
-        bb.put((byte) (v & 0xff));
-    }
-
-    /**
-     * Put an unsigned byte into the specified ByteBuffer at the specified
-     * offset
-     *
-     * @param bb ByteBuffer to put the byte into
-     * @param v the short containing the unsigned byte
-     * @param offset the offset to insert the unsigned byte at
-     */
-    public static void putUnsignedByte(ByteBuffer bb, short v, int offset) {
-        bb.put(offset, (byte) (v & 0xff));
-    }
-
-    /**
-     * Get an unsigned short from the current position of the ByteBuffer
-     *
-     * @param bb ByteBuffer to get the byte from
-     * @return an unsigned short contained in a int
-     */
-    public static int getUnsignedShort(ByteBuffer bb) {
-        return (bb.getShort() & 0xffff);
-    }
-
-    /**
-     * Get an unsigned short from the specified offset in the ByteBuffer
-     *
-     * @param bb ByteBuffer to get the short from
-     * @param offset the offset to get the short from
-     * @return an unsigned short contained in a int
-     */
-    public static int getUnsignedShort(ByteBuffer bb, int offset) {
-        return (bb.getShort(offset) & 0xffff);
-    }
-
-    /**
-     * Put an unsigned short into the specified ByteBuffer at the current
-     * position
-     *
-     * @param bb ByteBuffer to put the short into
-     * @param v the int containing the unsigned short
-     */
-    public static void putUnsignedShort(ByteBuffer bb, int v) {
-        bb.putShort((short) (v & 0xffff));
-    }
-
-    /**
-     * Put an unsigned short into the specified ByteBuffer at the specified
-     * offset
-     *
-     * @param bb ByteBuffer to put the short into
-     * @param v the int containing the unsigned short
-     * @param offset the offset to insert the unsigned short at
-     */
-    public static void putUnsignedShort(ByteBuffer bb, int v, int offset) {
-        bb.putShort(offset, (short) (v & 0xffff));
-    }
-
-    /**
-     * Get an unsigned int from the current position of the ByteBuffer
-     *
-     * @param bb ByteBuffer to get the int from
-     * @return an unsigned int contained in a long
-     */
-    public static long getUnsignedInt(ByteBuffer bb) {
-        return ((long) bb.getInt() & 0xffffffffL);
-    }
-
-    /**
-     * Get an unsigned int from the specified offset in the ByteBuffer
-     *
-     * @param bb ByteBuffer to get the int from
-     * @param offset the offset to get the int from
-     * @return an unsigned int contained in a long
-     */
-    public static long getUnsignedInt(ByteBuffer bb, int offset) {
-        return ((long) bb.getInt(offset) & 0xffffffffL);
-    }
-
-    /**
-     * Put an unsigned int into the specified ByteBuffer at the current position
-     *
-     * @param bb ByteBuffer to put the int into
-     * @param v the long containing the unsigned int
-     */
-    public static void putUnsignedInt(ByteBuffer bb, long v) {
-        bb.putInt((int) (v & 0xffffffffL));
-    }
-
-    /**
-     * Put an unsigned int into the specified ByteBuffer at the specified offset
-     *
-     * @param bb ByteBuffer to put the int into
-     * @param v the long containing the unsigned int
-     * @param offset the offset to insert the unsigned int at
-     */
-    public static void putUnsignedInt(ByteBuffer bb, long v, int offset) {
-        bb.putInt(offset, (int) (v & 0xffffffffL));
-    }
-
-    /**
-     * Get an unsigned long from the current position of the ByteBuffer
-     *
-     * @param bb ByteBuffer to get the long from
-     * @return an unsigned long contained in a BigInteger
-     */
-    public static BigInteger getUnsignedLong(ByteBuffer bb) {
-        byte[] v = new byte[8];
-        for (int i = 0; i < 8; ++i) {
-            v[i] = bb.get(i);
-        }
-        return new BigInteger(1, v);
-    }
-
-    /**
-     * Get an unsigned long from the specified offset in the ByteBuffer
-     *
-     * @param bb ByteBuffer to get the long from
-     * @param offset the offset to get the long from
-     * @return an unsigned long contained in a BigInteger
-     */
-    public static BigInteger getUnsignedLong(ByteBuffer bb, int offset) {
-        byte[] v = new byte[8];
-        for (int i = 0; i < 8; ++i) {
-            v[i] = bb.get(offset+i);
-        }
-        return new BigInteger(1, v);
-    }
-
-    /**
-     * Put an unsigned long into the specified ByteBuffer at the current
-     * position
-     *
-     * @param bb ByteBuffer to put the long into
-     * @param v the BigInteger containing the unsigned long
-     */
-    public static void putUnsignedLong(ByteBuffer bb, BigInteger v) {
-        bb.putLong(v.longValue());
-    }
-
-    /**
-     * Put an unsigned long into the specified ByteBuffer at the specified
-     * offset
-     *
-     * @param bb  ByteBuffer to put the long into
-     * @param v the BigInteger containing the unsigned long
-     * @param offset the offset to insert the unsigned long at
-     */
-    public static void putUnsignedLong(ByteBuffer bb, BigInteger v, int offset) {
-        bb.putLong(offset, v.longValue());
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java b/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java
deleted file mode 100644
index 687d5449f..000000000
--- a/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.vendor.nicira;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.vendor.OFVendorData;
-
-/**
- * Base class for vendor data corresponding to a Nicira vendor extension.
- * Nicira vendor data always starts with a 4-byte integer data type value.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public class OFNiciraVendorData implements OFVendorData {
-
-    public static final int NX_VENDOR_ID = 0x00002320;
-    /**
-     * The value of the integer data type at the beginning of the vendor data
-     */
-    protected int dataType;
-    
-    /**
-     * Construct empty (i.e. unspecified data type) Nicira vendor data.
-     */
-    public OFNiciraVendorData() {
-    }
-    
-    /**
-     * Contruct Nicira vendor data with the specified data type
-     * @param dataType the data type value at the beginning of the vendor data.
-     */
-    public OFNiciraVendorData(int dataType) {
-        this.dataType = dataType;
-    }
-    
-    /**
-     * Get the data type value at the beginning of the vendor data
-     * @return the integer data type value
-     */
-    public int getDataType() {
-        return dataType;
-    }
-    
-    /**
-     * Set the data type value
-     * @param dataType the integer data type value at the beginning of the
-     *     vendor data.
-     */
-    public void setDataType(int dataType) {
-        this.dataType = dataType;
-    }
-    
-    /**
-     * Get the length of the vendor data. This implementation will normally
-     * be the superclass for another class that will override this to return
-     * the overall vendor data length. This implementation just returns the 
-     * length of the part that includes the 4-byte integer data type value
-     * at the beginning of the vendor data.
-     */
-    @Override
-    public int getLength() {
-        return 4;
-    }
-
-    /**
-     * Read the vendor data from the ChannelBuffer
-     * @param data the channel buffer from which we're deserializing
-     * @param length the length to the end of the enclosing message
-     */
-    @Override
-    public void readFrom(ChannelBuffer data, int length) {
-        dataType = data.readInt();
-    }
-
-    /**
-     * Write the vendor data to the ChannelBuffer
-     * @param data the channel buffer to which we're serializing
-     */
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeInt(dataType);
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java b/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java
deleted file mode 100644
index 98f88b242..000000000
--- a/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.openflow.vendor.nicira;
-
-import org.openflow.protocol.vendor.OFBasicVendorDataType;
-import org.openflow.protocol.vendor.OFBasicVendorId;
-import org.openflow.protocol.vendor.OFVendorId;
-
-public class OFNiciraVendorExtensions {
-    private static boolean initialized = false;
-
-    public static synchronized void initialize() {
-        if (initialized)
-            return;
-
-        // Configure openflowj to be able to parse the role request/reply
-        // vendor messages.
-        OFBasicVendorId niciraVendorId =
-                new OFBasicVendorId(OFNiciraVendorData.NX_VENDOR_ID, 4);
-        OFVendorId.registerVendorId(niciraVendorId);
-        OFBasicVendorDataType roleRequestVendorData =
-                new OFBasicVendorDataType(OFRoleRequestVendorData.NXT_ROLE_REQUEST,
-                        OFRoleRequestVendorData.getInstantiable());
-        niciraVendorId.registerVendorDataType(roleRequestVendorData);
-        OFBasicVendorDataType roleReplyVendorData =
-                new OFBasicVendorDataType(OFRoleReplyVendorData.NXT_ROLE_REPLY,
-                        OFRoleReplyVendorData.getInstantiable());
-        niciraVendorId.registerVendorDataType(roleReplyVendorData);
-
-        initialized = true;
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java b/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java
deleted file mode 100644
index fa28c71fb..000000000
--- a/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.vendor.nicira;
-
-import org.openflow.protocol.Instantiable;
-import org.openflow.protocol.vendor.OFVendorData;
-
-/**
- * Subclass of OFVendorData representing the vendor data associated with
- * a role reply vendor extension.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public class OFRoleReplyVendorData extends OFRoleVendorData {
-
-    protected static Instantiable<OFVendorData> instantiable =
-            new Instantiable<OFVendorData>() {
-                public OFVendorData instantiate() {
-                    return new OFRoleReplyVendorData();
-                }
-            };
-
-    /**
-     * @return a subclass of Instantiable<OFVendorData> that instantiates
-     *         an instance of OFRoleReplyVendorData.
-     */
-    public static Instantiable<OFVendorData> getInstantiable() {
-        return instantiable;
-    }
-
-    /**
-     * The data type value for a role reply
-     */
-    public static final int NXT_ROLE_REPLY = 11;
-
-    /**
-     * Construct a role reply vendor data with an unspecified role value.
-     */
-    public OFRoleReplyVendorData() {
-        super(NXT_ROLE_REPLY);
-    }
-    
-    /**
-     * Construct a role reply vendor data with the specified role value.
-     * @param role the role value for the role reply. Should be one of
-     *      NX_ROLE_OTHER, NX_ROLE_MASTER or NX_ROLE_SLAVE.
-     */
-    public OFRoleReplyVendorData(int role) {
-        super(NXT_ROLE_REPLY, role);
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java b/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java
deleted file mode 100644
index e7dbe71bd..000000000
--- a/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.vendor.nicira;
-
-import org.openflow.protocol.Instantiable;
-import org.openflow.protocol.vendor.OFVendorData;
-
-/**
- * Subclass of OFVendorData representing the vendor data associated with
- * a role request vendor extension.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public class OFRoleRequestVendorData extends OFRoleVendorData {
-
-    protected static Instantiable<OFVendorData> instantiable =
-            new Instantiable<OFVendorData>() {
-                public OFVendorData instantiate() {
-                    return new OFRoleRequestVendorData();
-                }
-            };
-
-    /**
-     * @return a subclass of Instantiable<OFVendorData> that instantiates
-     *         an instance of OFRoleRequestVendorData.
-     */
-    public static Instantiable<OFVendorData> getInstantiable() {
-        return instantiable;
-    }
-
-    /**
-     * The data type value for a role request
-     */
-    public static final int NXT_ROLE_REQUEST = 10;
-
-    /**
-     * Construct a role request vendor data with an unspecified role value.
-     */
-    public OFRoleRequestVendorData() {
-        super(NXT_ROLE_REQUEST);
-    }
-    
-    /**
-     * Construct a role request vendor data with the specified role value.
-     * @param role the role value for the role request. Should be one of
-     *      NX_ROLE_OTHER, NX_ROLE_MASTER or NX_ROLE_SLAVE.
-     */
-    public OFRoleRequestVendorData(int role) {
-        super(NXT_ROLE_REQUEST, role);
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java b/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java
deleted file mode 100644
index e7c8bf213..000000000
--- a/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson & Rob Sherwood, Stanford University
-* 
-*    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 org.openflow.vendor.nicira;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-/**
- * Class that represents the vendor data in the role request
- * extension implemented by Open vSwitch to support high availability.
- * 
- * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
- */
-public class OFRoleVendorData extends OFNiciraVendorData {
-    
-    /**
-     * Role value indicating that the controller is in the OTHER role.
-     */
-    public static final int NX_ROLE_OTHER = 0;
-    
-    /**
-     * Role value indicating that the controller is in the MASTER role.
-     */
-    public static final int NX_ROLE_MASTER = 1;
-    
-    /**
-     * Role value indicating that the controller is in the SLAVE role.
-     */
-    public static final int NX_ROLE_SLAVE = 2;
-
-    protected int role;
-
-    /** 
-     * Construct an uninitialized OFRoleVendorData
-     */
-    public OFRoleVendorData() {
-        super();
-    }
-    
-    /**
-     * Construct an OFRoleVendorData with the specified data type
-     * (i.e. either request or reply) and an unspecified role.
-     * @param dataType
-     */
-    public OFRoleVendorData(int dataType) {
-        super(dataType);
-    }
-    
-    /**
-     * Construct an OFRoleVendorData with the specified data type
-     * (i.e. either request or reply) and role (i.e. one of of
-     * master, slave, or other).
-     * @param dataType either role request or role reply data type
-     */
-    public OFRoleVendorData(int dataType, int role) {
-        super(dataType);
-        this.role = role;
-    }
-    /**
-     * @return the role value of the role vendor data
-     */
-    public int getRole() {
-        return role;
-    }
-    
-    /**
-     * @param role the role value of the role vendor data
-     */
-    public void setRole(int role) {
-        this.role = role;
-    }
-
-    /**
-     * @return the total length of the role vendor data
-     */
-    @Override
-    public int getLength() {
-        return super.getLength() + 4;
-    }
-    
-    /**
-     * Read the role vendor data from the ChannelBuffer
-     * @param data the channel buffer from which we're deserializing
-     * @param length the length to the end of the enclosing message
-     */
-    public void readFrom(ChannelBuffer data, int length) {
-        super.readFrom(data, length);
-        role = data.readInt();
-    }
-
-    /**
-     * Write the role vendor data to the ChannelBuffer
-     * @param data the channel buffer to which we're serializing
-     */
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeInt(role);
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java b/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java
deleted file mode 100644
index 9be821f2a..000000000
--- a/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.vendor.openflow;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.vendor.OFVendorData;
-
-/**
- * Base class for vendor data corresponding to extensions to OpenFlow 1.0.
- * Based on org.openflow.vendor.nicira
- *
- * @author Andrew Ferguson (adf@cs.brown.edu)
- */
-public class OFOpenFlowVendorData implements OFVendorData {
-
-    public static final int OF_VENDOR_ID = 0x000026e1;
-
-    /**
-     * The value of the integer data type at the beginning of the vendor data
-     */
-    protected int dataType;
-
-    /**
-     * Construct empty (i.e. unspecified data type) OpenFlow vendor data.
-     */
-    public OFOpenFlowVendorData() {
-    }
-
-    /**
-     * Construct OpenFlow vendor data with the specified data type
-     * @param dataType the data type value at the beginning of the vendor data.
-     */
-    public OFOpenFlowVendorData(int dataType) {
-        this.dataType = dataType;
-    }
-
-    /**
-     * Get the data type value at the beginning of the vendor data
-     * @return the integer data type value
-     */
-    public int getDataType() {
-        return dataType;
-    }
-
-    /**
-     * Set the data type value
-     * @param dataType the integer data type value at the beginning of the
-     *     vendor data.
-     */
-    public void setDataType(int dataType) {
-        this.dataType = dataType;
-    }
-
-    /**
-     * Get the length of the vendor data. This implementation will normally
-     * be the superclass for another class that will override this to return
-     * the overall vendor data length. This implementation just returns the
-     * length of the part that includes the 4-byte integer data type value
-     * at the beginning of the vendor data.
-     */
-    @Override
-    public int getLength() {
-        return 4;
-    }
-
-    /**
-     * Read the vendor data from the ChannelBuffer
-     * @param data the channel buffer from which we're deserializing
-     * @param length the length to the end of the enclosing message
-     */
-    @Override
-    public void readFrom(ChannelBuffer data, int length) {
-        dataType = data.readInt();
-    }
-
-    /**
-     * Write the vendor data to the ChannelBuffer
-     * @param data the channel buffer to which we're serializing
-     */
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        data.writeInt(dataType);
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java b/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java
deleted file mode 100644
index 3fa10298c..000000000
--- a/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.vendor.openflow;
-
-import org.openflow.protocol.vendor.OFBasicVendorDataType;
-import org.openflow.protocol.vendor.OFBasicVendorId;
-import org.openflow.protocol.vendor.OFVendorId;
-
-public class OFOpenFlowVendorExtensions {
-    private static boolean initialized = false;
-
-    public static synchronized void initialize() {
-        if (initialized)
-            return;
-
-        // Configure openflowj to be able to parse the OpenFlow extensions.
-        OFBasicVendorId openflowVendorId =
-                new OFBasicVendorId(OFOpenFlowVendorData.OF_VENDOR_ID, 4);
-        OFVendorId.registerVendorId(openflowVendorId);
-
-        OFBasicVendorDataType queueModifyVendorData =
-                new OFBasicVendorDataType(OFQueueModifyVendorData.OFP_EXT_QUEUE_MODIFY,
-                        OFQueueModifyVendorData.getInstantiable());
-        openflowVendorId.registerVendorDataType(queueModifyVendorData);
-
-        OFBasicVendorDataType queueDeleteVendorData =
-                new OFBasicVendorDataType(OFQueueDeleteVendorData.OFP_EXT_QUEUE_DELETE,
-                        OFQueueModifyVendorData.getInstantiable());
-        openflowVendorId.registerVendorDataType(queueDeleteVendorData);
-
-        initialized = true;
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java b/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java
deleted file mode 100644
index 4fc52bacb..000000000
--- a/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.vendor.openflow;
-
-import org.openflow.protocol.Instantiable;
-import org.openflow.protocol.vendor.OFVendorData;
-
-/**
- * Class that represents the vendor data in the queue delete request
- *
- * @author Andrew Ferguson (adf@cs.brown.edu)
- */
-public class OFQueueDeleteVendorData extends OFQueueVendorData {
-
-    protected static Instantiable<OFVendorData> instantiable =
-            new Instantiable<OFVendorData>() {
-                public OFVendorData instantiate() {
-                    return new OFQueueDeleteVendorData();
-                }
-            };
-
-    /**
-     * @return a subclass of Instantiable<OFVendorData> that instantiates
-     *         an instance of OFQueueDeleteVendorData.
-     */
-    public static Instantiable<OFVendorData> getInstantiable() {
-        return instantiable;
-    }
-
-    /**
-     * The data type value for a queue delete request
-     */
-    public static final int OFP_EXT_QUEUE_DELETE = 1;
-
-    public OFQueueDeleteVendorData() {
-        super(OFP_EXT_QUEUE_DELETE);
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java b/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java
deleted file mode 100644
index 0d2f31b52..000000000
--- a/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.vendor.openflow;
-
-import org.openflow.protocol.Instantiable;
-import org.openflow.protocol.vendor.OFVendorData;
-
-/**
- * Class that represents the vendor data in the queue modify request
- *
- * @author Andrew Ferguson (adf@cs.brown.edu)
- */
-public class OFQueueModifyVendorData extends OFQueueVendorData {
-
-    protected static Instantiable<OFVendorData> instantiable =
-            new Instantiable<OFVendorData>() {
-                public OFVendorData instantiate() {
-                    return new OFQueueModifyVendorData();
-                }
-            };
-
-    /**
-     * @return a subclass of Instantiable<OFVendorData> that instantiates
-     *         an instance of OFQueueModifyVendorData.
-     */
-    public static Instantiable<OFVendorData> getInstantiable() {
-        return instantiable;
-    }
-
-    /**
-     * The data type value for a queue modify request
-     */
-    public static final int OFP_EXT_QUEUE_MODIFY = 0;
-
-    public OFQueueModifyVendorData() {
-        super(OFP_EXT_QUEUE_MODIFY);
-    }
-}
diff --git a/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java b/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java
deleted file mode 100644
index eeae9aace..000000000
--- a/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
-*    Copyright 2012, Andrew Ferguson, Brown University
-*
-*    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 org.openflow.vendor.openflow;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.OFPacketQueue;
-
-/**
- * Class that represents the vendor data in a queue modify or delete request
- *
- * @author Andrew Ferguson (adf@cs.brown.edu)
- */
-public class OFQueueVendorData extends OFOpenFlowVendorData {
-    public static int MINIMUM_LENGTH = 8;
-
-    protected short portNumber;
-    protected List<OFPacketQueue> queues = new ArrayList<OFPacketQueue>();
-
-    public OFQueueVendorData(int dataType) {
-        super(dataType);
-    }
-
-    /**
-     * @return the portNumber
-     */
-    public short getPortNumber() {
-        return portNumber;
-    }
-
-    /**
-     * @param port the port on which the queue is
-     */
-    public void setPortNumber(short portNumber) {
-        this.portNumber = portNumber;
-    }
-
-
-    /**
-     * @return the queues
-     */
-    public List<OFPacketQueue> getQueues() {
-        return queues;
-    }
-
-    /**
-     * @param queues the queues to modify or delete
-     */
-    public void setQueues(List<OFPacketQueue> queues) {
-        this.queues = queues;
-    }
-
-    /**
-     * @return the total length of the queue modify or delete msg
-     */
-    @Override
-    public int getLength() {
-        int queuesLength = 0;
-
-        for (OFPacketQueue queue : queues) {
-            queuesLength += queue.getLength();
-        }
-
-        return super.getLength() + MINIMUM_LENGTH + queuesLength;
-    }
-
-    /**
-     * Read the queue message data from the ChannelBuffer
-     * @param data the channel buffer from which we're deserializing
-     * @param length the length to the end of the enclosing message
-     */
-    public void readFrom(ChannelBuffer data, int length) {
-        super.readFrom(data, length);
-        portNumber = data.readShort();
-        data.readInt();   // pad
-        data.readShort(); // pad
-
-        int availLength = (length - MINIMUM_LENGTH);
-        this.queues.clear();
-
-        while (availLength > 0) {
-            OFPacketQueue queue = new OFPacketQueue();
-            queue.readFrom(data);
-            queues.add(queue);
-            availLength -= queue.getLength();
-        }
-    }
-
-    /**
-     * Write the queue message data to the ChannelBuffer
-     * @param data the channel buffer to which we're serializing
-     */
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeShort(this.portNumber);
-        data.writeInt(0);   // pad
-        data.writeShort(0); // pad
-
-        for (OFPacketQueue queue : queues) {
-            queue.writeTo(data);
-        }
-    }
-}
diff --git a/src/main/java/org/sdnplatform/sync/ISyncService.java b/src/main/java/org/sdnplatform/sync/ISyncService.java
index 75f3948a8..48feead4a 100644
--- a/src/main/java/org/sdnplatform/sync/ISyncService.java
+++ b/src/main/java/org/sdnplatform/sync/ISyncService.java
@@ -40,6 +40,8 @@ public interface ISyncService extends IFloodlightService {
          */
         UNSYNCHRONIZED
     }
+    
+    public short getLocalNodeId();
 
     /**
      * Create a store with the given store name and scope
diff --git a/src/main/java/org/sdnplatform/sync/internal/SyncTorture.java b/src/main/java/org/sdnplatform/sync/internal/SyncTorture.java
deleted file mode 100644
index 74e4ae966..000000000
--- a/src/main/java/org/sdnplatform/sync/internal/SyncTorture.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package org.sdnplatform.sync.internal;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.sdnplatform.sync.IStoreClient;
-import org.sdnplatform.sync.ISyncService;
-import org.sdnplatform.sync.Versioned;
-import org.sdnplatform.sync.ISyncService.Scope;
-import org.sdnplatform.sync.error.SyncException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-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.IDebugCounterService;
-
-/**
- * A floodlight module that will start up and start doing horrible,
- * horrible things to the sync service.
- * @author readams
- */
-public class SyncTorture implements IFloodlightModule {
-    protected static final Logger logger =
-            LoggerFactory.getLogger(SyncTorture.class);
-
-    private static final String SYNC_STORE_NAME =
-            SyncTorture.class.getCanonicalName() + ".torture";
-    
-    ISyncService syncService;
-    IDebugCounterService debugCounter;
-
-    int numWorkers = 2;
-    int keysPerWorker = 1024*1024;
-    int iterations = 0;
-    int delay = 0;
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleServices() {
-        return null;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        return null;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleDependencies() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(ISyncService.class);
-        l.add(IDebugCounterService.class);
-
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)
-            throws FloodlightModuleException {
-        syncService = context.getServiceImpl(ISyncService.class);
-        debugCounter = context.getServiceImpl(IDebugCounterService.class);
-
-        try {
-            syncService.registerStore(SYNC_STORE_NAME, Scope.GLOBAL);
-        } catch (SyncException e) {
-            throw new FloodlightModuleException(e);
-        }
-        
-        Map<String,String> config = context.getConfigParams(this);
-        if (config.containsKey("numWorkers")) {
-            numWorkers = Integer.parseInt(config.get("numWorkers"));
-        }
-        if (config.containsKey("keysPerWorker")) {
-            keysPerWorker = Integer.parseInt(config.get("keysPerWorker"));
-        }
-        if (config.containsKey("iterations")) {
-            iterations = Integer.parseInt(config.get("iterations"));
-        }
-        if (config.containsKey("delay")) {
-            delay = Integer.parseInt(config.get("delay"));
-        }
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context)
-            throws FloodlightModuleException {
-        try {
-            final IStoreClient<String, TortureValue> storeClient = 
-                    syncService.getStoreClient(SYNC_STORE_NAME, 
-                                               String.class, 
-                                               TortureValue.class);
-            for (int i = 0; i < numWorkers; i++) {
-                Thread thread = new Thread(new TortureWorker(storeClient, i),
-                                           "Torture-" + i);
-                thread.setPriority(Thread.MIN_PRIORITY);
-                thread.start();
-            }
-        } catch (Exception e) {
-            throw new FloodlightModuleException(e);
-        }
-    }
-
-    protected static class TortureValue {
-        private String string;
-        private int integer;
-        private boolean bool;
-
-        public TortureValue() {
-            super();
-        }
-
-        public TortureValue(String string, int integer, boolean bool) {
-            super();
-            this.string = string;
-            this.integer = integer;
-            this.bool = bool;
-        }
-        
-        public String getString() {
-            return string;
-        }
-        public void setString(String string) {
-            this.string = string;
-        }
-        public int getInteger() {
-            return integer;
-        }
-        public void setInteger(int integer) {
-            this.integer = integer;
-        }
-        public boolean isBool() {
-            return bool;
-        }
-        public void setBool(boolean bool) {
-            this.bool = bool;
-        }
-    }
-    
-    protected class TortureWorker implements Runnable {
-        final IStoreClient<String, TortureValue> storeClient;
-        final int workerId;
-        final List<TortureValue> values;
-
-        public TortureWorker(IStoreClient<String, TortureValue> storeClient,
-                             int workerId) {
-            super();
-            this.storeClient = storeClient;
-            this.workerId = workerId;
-            values = new ArrayList<TortureValue>();
-            for (int i = 0; i < keysPerWorker; i++) {
-                values.add(new TortureValue(workerId+":"+i, 0, true));
-            }
-        }
-
-        @Override
-        public void run() {
-            if (delay > 0) {
-                try {
-                    Thread.sleep(delay);
-                } catch (InterruptedException e) { }
-            }
-            int i = 0;
-            while (iterations == 0 || i++ < iterations) {
-                long start = System.currentTimeMillis();
-                try {
-                    for (TortureValue v : values) {
-                        Versioned<TortureValue> vv =
-                                storeClient.get(v.getString());
-                        v.setInteger(v.getInteger() + 1);
-                        v.setBool(!v.isBool());
-                        vv.setValue(v);
-                        storeClient.put(v.getString(), vv);
-                    }
-                } catch (Exception e) {
-                    logger.error("Error in worker: ", e);
-                }
-                long iterend = System.currentTimeMillis();
-                debugCounter.flushCounters();
-                logger.info("Completed iteration of {} values in {}ms" + 
-                            " ({}/s)", 
-                            new Object[]{values.size(), (iterend-start),
-                            1000*values.size()/(iterend-start)});
-            }
-            
-        }
-    }
-}
diff --git a/src/main/java/org/sdnplatform/sync/internal/config/ClusterConfig.java b/src/main/java/org/sdnplatform/sync/internal/config/ClusterConfig.java
index 27addf7fe..416f4ebaa 100644
--- a/src/main/java/org/sdnplatform/sync/internal/config/ClusterConfig.java
+++ b/src/main/java/org/sdnplatform/sync/internal/config/ClusterConfig.java
@@ -15,6 +15,7 @@ import org.sdnplatform.sync.error.SyncException;
  * @author readams
  */
 public class ClusterConfig {
+    public static final short NODE_ID_UNCONFIGURED = Short.MAX_VALUE;
 
     private HashMap<Short, Node> allNodes =
             new HashMap<Short, Node>();
diff --git a/src/main/java/org/sdnplatform/sync/internal/util/ByteArray.java b/src/main/java/org/sdnplatform/sync/internal/util/ByteArray.java
index 5a9473562..733f03af8 100644
--- a/src/main/java/org/sdnplatform/sync/internal/util/ByteArray.java
+++ b/src/main/java/org/sdnplatform/sync/internal/util/ByteArray.java
@@ -4,7 +4,7 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.util.HexString;
 
 /**
  * A byte array container that provides an equals and hashCode pair based on the
diff --git a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
index b06589a30..e5b334780 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
@@ -95,7 +95,7 @@ import org.sdnplatform.sync.test.MockSyncService;
 
 public class ControllerTest extends FloodlightTestCase {
 
-    private Controller controller;
+    private OLD__Controller controller;
     private MockThreadPoolService tp;
     private MockSyncService syncService;
     private IStoreClient<Long, SwitchSyncRepresentation> storeClient;
@@ -115,7 +115,7 @@ public class ControllerTest extends FloodlightTestCase {
 
         FloodlightProvider cm = new FloodlightProvider();
         fmc.addConfigParam(cm, "role", role.toString());
-        controller = (Controller)cm.getServiceImpls().get(IFloodlightProviderService.class);
+        controller = (OLD__Controller)cm.getServiceImpls().get(IFloodlightProviderService.class);
         fmc.addService(IFloodlightProviderService.class, controller);
 
         MemoryStorageSource memstorage = new MemoryStorageSource();
@@ -165,7 +165,7 @@ public class ControllerTest extends FloodlightTestCase {
         cm.startUp(fmc);
 
         storeClient =
-                syncService.getStoreClient(Controller.SWITCH_SYNC_STORE_NAME,
+                syncService.getStoreClient(OLD__Controller.SWITCH_SYNC_STORE_NAME,
                                            Long.class,
                                            SwitchSyncRepresentation.class);
 
@@ -204,7 +204,7 @@ public class ControllerTest extends FloodlightTestCase {
                    controller.isUpdateQueueEmptyForTesting());
     }
 
-    public Controller getController() {
+    public OLD__Controller getController() {
         return controller;
     }
 
@@ -2048,11 +2048,11 @@ public class ControllerTest extends FloodlightTestCase {
     private Map<String,Object> getFakeControllerIPRow(String id, String controllerId,
             String type, int number, String discoveredIP ) {
         HashMap<String, Object> row = new HashMap<String,Object>();
-        row.put(Controller.CONTROLLER_INTERFACE_ID, id);
-        row.put(Controller.CONTROLLER_INTERFACE_CONTROLLER_ID, controllerId);
-        row.put(Controller.CONTROLLER_INTERFACE_TYPE, type);
-        row.put(Controller.CONTROLLER_INTERFACE_NUMBER, number);
-        row.put(Controller.CONTROLLER_INTERFACE_DISCOVERED_IP, discoveredIP);
+        row.put(OLD__Controller.CONTROLLER_INTERFACE_ID, id);
+        row.put(OLD__Controller.CONTROLLER_INTERFACE_CONTROLLER_ID, controllerId);
+        row.put(OLD__Controller.CONTROLLER_INTERFACE_TYPE, type);
+        row.put(OLD__Controller.CONTROLLER_INTERFACE_NUMBER, number);
+        row.put(OLD__Controller.CONTROLLER_INTERFACE_DISCOVERED_IP, discoveredIP);
         return row;
     }
 
@@ -2139,7 +2139,7 @@ public class ControllerTest extends FloodlightTestCase {
         synchronized(listener) {
             // Insert a first entry
             controller.getStorageSourceService()
-                .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
+                .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME,
                     getFakeControllerIPRow("row1", "c1", "Ethernet", 0, "1.1.1.1"));
             expectedCurMap.clear();
             expectedAddedMap.clear();
@@ -2151,7 +2151,7 @@ public class ControllerTest extends FloodlightTestCase {
 
             // Add an interface that we want to ignore.
             controller.getStorageSourceService()
-                .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
+                .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME,
                     getFakeControllerIPRow("row2", "c1", "Ethernet", 1, "1.1.1.2"));
             // TODO: do a different check. This call will have to wait for the timeout
             controller.processUpdateQueueForTesting();
@@ -2160,7 +2160,7 @@ public class ControllerTest extends FloodlightTestCase {
 
             // Add another entry
             controller.getStorageSourceService()
-                .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
+                .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME,
                     getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.2"));
             expectedCurMap.clear();
             expectedAddedMap.clear();
@@ -2174,7 +2174,7 @@ public class ControllerTest extends FloodlightTestCase {
 
             // Update an entry
             controller.getStorageSourceService()
-                .updateRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
+                .updateRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME,
                     "row3", getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.3"));
             expectedCurMap.clear();
             expectedAddedMap.clear();
@@ -2188,7 +2188,7 @@ public class ControllerTest extends FloodlightTestCase {
 
             // Delete an entry
             controller.getStorageSourceService()
-                .deleteRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME, "row3");
+                .deleteRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME, "row3");
             expectedCurMap.clear();
             expectedAddedMap.clear();
             expectedRemovedMap.clear();
@@ -2204,13 +2204,13 @@ public class ControllerTest extends FloodlightTestCase {
         HashMap<String,String> expectedCurMap = new HashMap<String, String>();
 
         controller.getStorageSourceService()
-            .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
+            .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME,
                 getFakeControllerIPRow("row1", "c1", "Ethernet", 0, "1.1.1.1"));
         controller.getStorageSourceService()
-            .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
+            .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME,
                 getFakeControllerIPRow("row2", "c1", "Ethernet", 1, "1.1.1.2"));
         controller.getStorageSourceService()
-            .insertRow(Controller.CONTROLLER_INTERFACE_TABLE_NAME,
+            .insertRow(OLD__Controller.CONTROLLER_INTERFACE_TABLE_NAME,
                 getFakeControllerIPRow("row3", "c2", "Ethernet", 0, "2.2.2.2"));
         expectedCurMap.put("c1", "1.1.1.1");
         expectedCurMap.put("c2", "2.2.2.2");
diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java
index ed01868b0..bc4490e73 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/OFChannelHandlerTest.java
@@ -66,7 +66,7 @@ import static org.junit.Assert.*;
 public class OFChannelHandlerTest {
     private static final short CORE_PRIORITY = 4242;
     private static final short ACCESS_PRIORITY = 42;
-    private Controller controller;
+    private OLD__Controller controller;
     private IThreadPoolService threadPool;
     private IDebugCounterService debugCounterService;
     private OFChannelHandler handler;
@@ -110,7 +110,7 @@ public class OFChannelHandlerTest {
 
     @Before
     public void setUp() throws Exception {
-        controller = createMock(Controller.class);
+        controller = createMock(OLD__Controller.class);
         threadPool = createMock(IThreadPoolService.class);
         ctx = createMock(ChannelHandlerContext.class);
         channelStateEvent = createMock(ChannelStateEvent.class);
@@ -125,8 +125,8 @@ public class OFChannelHandlerTest {
         // TODO: should mock IDebugCounterService and make sure
         // the expected counters are updated.
         debugCounterService = new DebugCounter();
-        Controller.Counters counters =
-                new Controller.Counters();
+        OLD__Controller.Counters counters =
+                new OLD__Controller.Counters();
         counters.createCounters(debugCounterService);
         expect(controller.getCounters()).andReturn(counters).anyTimes();
         replay(controller);
@@ -442,7 +442,7 @@ public class OFChannelHandlerTest {
         Iterator<IResultSet> it = null;
 
         if (cfg.isPresent) {
-            storageResultSet.getBoolean(Controller.SWITCH_CONFIG_CORE_SWITCH);
+            storageResultSet.getBoolean(OLD__Controller.SWITCH_CONFIG_CORE_SWITCH);
             expectLastCall().andReturn(cfg.isCoreSwitch).atLeastOnce();
             it = Collections.singletonList(storageResultSet).iterator();
         } else {
@@ -452,7 +452,7 @@ public class OFChannelHandlerTest {
         storageResultSet.close();
         expectLastCall().atLeastOnce();
         expect(storageResultSet.iterator()).andReturn(it).atLeastOnce();
-        storageSource.getRow(Controller.SWITCH_CONFIG_TABLE_NAME, cfg.dpid);
+        storageSource.getRow(OLD__Controller.SWITCH_CONFIG_TABLE_NAME, cfg.dpid);
         expectLastCall().andReturn(storageResultSet).atLeastOnce();
         replay(storageResultSet, storageSource);
     }
diff --git a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
index c3cc59ed3..1e5e4643e 100644
--- a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
+++ b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
@@ -30,7 +30,7 @@ import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.core.ImmutablePort;
-import net.floodlightcontroller.core.internal.Controller;
+import net.floodlightcontroller.core.internal.OLD__Controller;
 import net.floodlightcontroller.debugcounter.IDebugCounterService;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 
@@ -357,7 +357,7 @@ public class OFMessageDamperMockSwitch implements IOFSwitch {
     }
 
     @Override
-    public void setFloodlightProvider(Controller controller) {
+    public void setFloodlightProvider(OLD__Controller controller) {
         fail("Unexpected method call");
         // TODO Auto-generated method stub
 
diff --git a/src/test/java/org/openflow/protocol/BasicFactoryTest.java b/src/test/java/org/openflow/protocol/BasicFactoryTest.java
deleted file mode 100644
index 350d4be39..000000000
--- a/src/test/java/org/openflow/protocol/BasicFactoryTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-*
-*    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 org.openflow.protocol;
-
-import static org.junit.Assert.assertArrayEquals;
-
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.action.MockVendorAction;
-import org.openflow.protocol.action.MockVendorActionFactory;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionVendorGeneric;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.factory.MessageParseException;
-import org.openflow.protocol.factory.OFVendorActionRegistry;
-import org.openflow.util.U16;
-
-public class BasicFactoryTest extends TestCase {
-
-    public void testCreateAndParse() throws MessageParseException {
-        BasicFactory factory = BasicFactory.getInstance();
-        OFMessage m = factory.getMessage(OFType.HELLO);
-        m.setVersion((byte) 1);
-        m.setType(OFType.ECHO_REQUEST);
-        m.setLength(U16.t(8));
-        m.setXid(0xdeadbeef);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        ChannelBuffer bb2 = ChannelBuffers.dynamicBuffer();
-        m.writeTo(bb);
-        bb2.writeBytes(bb, bb.readableBytes()-1);
-        TestCase.assertNull(factory.parseMessage(bb2));
-        bb2.writeByte(bb.readByte());
-        List<OFMessage> message = factory.parseMessage(bb2);
-        TestCase.assertNotNull(message);
-        TestCase.assertEquals(message.size(), 1);
-        TestCase.assertTrue(message.get(0).getType() == OFType.ECHO_REQUEST);
-    }
-
-    public void testInvalidMsgParse() throws MessageParseException {
-        BasicFactory factory = BasicFactory.getInstance();
-        OFMessage m = factory.getMessage(OFType.HELLO);
-        m.setVersion((byte) 1);
-        m.setType(OFType.ECHO_REQUEST);
-        m.setLength(U16.t(16));
-        m.setXid(0xdeadbeef);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        m.writeTo(bb);
-        List<OFMessage> message = factory.parseMessage(bb);
-        TestCase.assertNull(message);
-    }
-
-    public void testCurrouptedMsgParse() throws MessageParseException {
-        BasicFactory factory = BasicFactory.getInstance();
-        OFMessage m = factory.getMessage(OFType.HELLO);
-        m.setVersion((byte) 1);
-        m.setType(OFType.ERROR);
-        m.setLength(U16.t(8));
-        m.setXid(0xdeadbeef);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        m.writeTo(bb);
-        try {
-                factory.parseMessage(bb);
-        }
-        catch(Exception e) {
-            TestCase.assertEquals(MessageParseException.class, e.getClass());
-        }
-    }
-
-    public void testCustomVendorAction() throws MessageParseException {
-        BasicFactory factory = BasicFactory.getInstance();
-        OFVendorActionRegistry.getInstance().register(
-                MockVendorAction.VENDOR_ID, new MockVendorActionFactory());
-
-
-        byte[] deadBeefMessage = {
-            (byte) 0xff, (byte) 0xff,          // action vendor
-            0x00, 0x10,                        // length
-            (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte)0xef,            // deadbeaf
-            0x01, 0x02, 0x03, 0x04,
-            0x05, 0x06, 0x07, 0x08               // pad
-        };
-
-        ChannelBuffer buf = ChannelBuffers.copiedBuffer(deadBeefMessage);
-
-        List<OFAction> actions = factory.parseActions(buf,deadBeefMessage.length);
-        assertEquals(1, actions.size());
-        OFAction ofAction = actions.get(0);
-        assertTrue("Action should be MockVendorAction, but is "+ofAction.getClass(), ofAction instanceof MockVendorAction);
-        assertArrayEquals( new byte[]  { 1,2,3,4,5,6,7,8}, ((MockVendorAction)ofAction).getMockData());
-
-
-    }
-
-    public void testGenericVendorAction() throws MessageParseException {
-        byte[] nonDeadBeefMessage = {
-                (byte) 0xff, (byte) 0xff,          // action vendor
-                0x00, 0x10,                        // length
-                (byte) 0x7e, (byte) 0xe7, (byte) 0xbe, (byte)0xef,            // deadbeaf
-                0x01, 0x02, 0x03, 0x04,
-                0x05, 0x06, 0x07, 0x08               // pad
-            };
-
-        BasicFactory factory = BasicFactory.getInstance();
-        OFVendorActionRegistry.getInstance().register(
-                MockVendorAction.VENDOR_ID, new MockVendorActionFactory());
-
-        ChannelBuffer buf = ChannelBuffers.copiedBuffer(nonDeadBeefMessage);
-
-        List<OFAction> actions = factory.parseActions(buf,nonDeadBeefMessage.length);
-        assertEquals(1, actions.size());
-        OFAction ofAction = actions.get(0);
-        assertTrue("Action should be OFActionVendorGeneric, but is "+ofAction.getClass(), ofAction instanceof OFActionVendorGeneric);
-    }
-
-}
diff --git a/src/test/java/org/openflow/protocol/OFActionTypeTest.java b/src/test/java/org/openflow/protocol/OFActionTypeTest.java
deleted file mode 100644
index ed8386cd7..000000000
--- a/src/test/java/org/openflow/protocol/OFActionTypeTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-
-import org.junit.Test;
-import org.openflow.protocol.action.OFActionType;
-
-import junit.framework.TestCase;
-
-
-public class OFActionTypeTest extends TestCase {
-    @Test
-    public void testMapping() throws Exception {
-        TestCase.assertEquals(OFActionType.OUTPUT,
-                OFActionType.valueOf((short) 0));
-        TestCase.assertEquals(OFActionType.OPAQUE_ENQUEUE,
-                OFActionType.valueOf((short) 11));
-        TestCase.assertEquals(OFActionType.VENDOR,
-                OFActionType.valueOf((short) 0xffff));
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java b/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java
deleted file mode 100644
index 7e447bb07..000000000
--- a/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.util.OFTestCase;
-
-public class OFBarrierReplyTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFBarrierReply msg = (OFBarrierReply) messageFactory
-                .getMessage(OFType.BARRIER_REPLY);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFType.BARRIER_REPLY, msg.getType());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java b/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java
deleted file mode 100644
index 3aa9cb4a7..000000000
--- a/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.util.OFTestCase;
-
-public class OFBarrierRequestTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFBarrierRequest msg = (OFBarrierRequest) messageFactory
-                .getMessage(OFType.BARRIER_REQUEST);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFType.BARRIER_REQUEST, msg.getType());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFErrorTest.java b/src/test/java/org/openflow/protocol/OFErrorTest.java
deleted file mode 100644
index f4a572698..000000000
--- a/src/test/java/org/openflow/protocol/OFErrorTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.OFError.OFErrorType;
-import org.openflow.protocol.OFError.OFHelloFailedCode;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.factory.MessageParseException;
-import org.openflow.protocol.factory.OFMessageFactory;
-import org.openflow.util.OFTestCase;
-
-public class OFErrorTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFError msg = (OFError) messageFactory.getMessage(OFType.ERROR);
-        msg.setMessageFactory(messageFactory);
-        msg.setErrorType(OFErrorType.OFPET_HELLO_FAILED.getValue());
-        msg.setErrorCode((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE
-                .ordinal());
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFErrorType.OFPET_HELLO_FAILED.getValue(),
-                msg.getErrorType());
-        TestCase.assertEquals((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE
-                .ordinal(), msg.getErrorType());
-        TestCase.assertNull(msg.getOffendingMsg());
-
-        msg.setOffendingMsg(new OFHello());
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFErrorType.OFPET_HELLO_FAILED.getValue(),
-                msg.getErrorType());
-        TestCase.assertEquals((short) OFHelloFailedCode.OFPHFC_INCOMPATIBLE
-                .ordinal(), msg.getErrorType());
-        TestCase.assertNotNull(msg.getOffendingMsg());
-        TestCase.assertEquals(OFHello.MINIMUM_LENGTH,
-                msg.getOffendingMsg().length);
-    }
-
-    public void testGarbageAtEnd() throws MessageParseException {
-        // This is a OFError msg (12 bytes), that encaps a OFVendor msg (24
-        // bytes)
-        // AND some zeros at the end (40 bytes) for a total of 76 bytes
-        // THIS is what an NEC sends in reply to Nox's VENDOR request
-        byte[] oferrorRaw = { 0x01, 0x01, 0x00, 0x4c, 0x00, 0x00, 0x10,
-                (byte) 0xcc, 0x00, 0x01, 0x00, 0x01, 0x01, 0x04, 0x00, 0x18,
-                0x00, 0x00, 0x10, (byte) 0xcc, 0x00, 0x00, 0x23, 0x20, 0x00,
-                0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00 };
-        OFMessageFactory factory = BasicFactory.getInstance();
-        ChannelBuffer oferrorBuf = 
-                ChannelBuffers.wrappedBuffer(oferrorRaw);
-        List<OFMessage> msg = factory.parseMessage(oferrorBuf);
-        TestCase.assertNotNull(msg);
-        TestCase.assertEquals(msg.size(), 1);
-        TestCase.assertEquals(76, msg.get(0).getLengthU());
-        ChannelBuffer out = ChannelBuffers.dynamicBuffer();
-        msg.get(0).writeTo(out);
-        TestCase.assertEquals(76, out.readableBytes());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java b/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java
deleted file mode 100644
index 62e491a99..000000000
--- a/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-
-import java.util.ArrayList;
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.util.OFTestCase;
-
-
-public class OFFeaturesReplyTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFFeaturesReply ofr = (OFFeaturesReply) messageFactory
-                .getMessage(OFType.FEATURES_REPLY);
-        List<OFPhysicalPort> ports = new ArrayList<OFPhysicalPort>();
-        OFPhysicalPort port = new OFPhysicalPort();
-        port.setHardwareAddress(new byte[6]);
-        port.setName("eth0");
-        ports.add(port);
-        ofr.setPorts(ports);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        ofr.writeTo(bb);
-        ofr.readFrom(bb);
-        TestCase.assertEquals(1, ofr.getPorts().size());
-        TestCase.assertEquals("eth0", ofr.getPorts().get(0).getName());
-
-        // test a 15 character name
-        ofr.getPorts().get(0).setName("012345678901234");
-        bb.clear();
-        ofr.writeTo(bb);
-        ofr.readFrom(bb);
-        TestCase.assertEquals("012345678901234", ofr.getPorts().get(0).getName());
-
-        // test a 16 character name getting truncated
-        ofr.getPorts().get(0).setName("0123456789012345");
-        bb.clear();
-        ofr.writeTo(bb);
-        ofr.readFrom(bb);
-        TestCase.assertEquals("012345678901234", ofr.getPorts().get(0).getName());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java b/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java
deleted file mode 100644
index 11746e724..000000000
--- a/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.OFFlowRemoved.OFFlowRemovedReason;
-import org.openflow.util.OFTestCase;
-
-public class OFFlowRemovedTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFFlowRemoved msg = (OFFlowRemoved) messageFactory
-                .getMessage(OFType.FLOW_REMOVED);
-        msg.setMatch(new OFMatch());
-        byte[] hwAddr = new byte[6];
-        msg.getMatch().setDataLayerDestination(hwAddr);
-        msg.getMatch().setDataLayerSource(hwAddr);
-        msg.setReason(OFFlowRemovedReason.OFPRR_DELETE);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFType.FLOW_REMOVED, msg.getType());
-        TestCase.assertEquals(OFFlowRemovedReason.OFPRR_DELETE, msg.getReason());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java b/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java
deleted file mode 100644
index c1f1f671a..000000000
--- a/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.util.OFTestCase;
-
-public class OFGetConfigReplyTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFSetConfig msg = (OFSetConfig) messageFactory
-                .getMessage(OFType.SET_CONFIG);
-        msg.setFlags((short) 1);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFType.SET_CONFIG, msg.getType());
-        TestCase.assertEquals((short)1, msg.getFlags());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java b/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java
deleted file mode 100644
index 94d9036e6..000000000
--- a/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.util.OFTestCase;
-
-public class OFGetConfigRequestTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFGetConfigRequest msg = (OFGetConfigRequest) messageFactory
-                .getMessage(OFType.GET_CONFIG_REQUEST);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFType.GET_CONFIG_REQUEST, msg.getType());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFMatchTest.java b/src/test/java/org/openflow/protocol/OFMatchTest.java
deleted file mode 100644
index fd7863acc..000000000
--- a/src/test/java/org/openflow/protocol/OFMatchTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-public class OFMatchTest extends TestCase {
-    public void testFromString() {
-        OFMatch correct = new OFMatch();
-        OFMatch tester = new OFMatch();
-
-        // Various combinations of "all"/"any"
-        tester.fromString("OFMatch[]");
-        // correct is already wildcarded
-        TestCase.assertEquals(correct, tester);
-        tester.fromString("all");
-        TestCase.assertEquals(correct, tester);
-        tester.fromString("ANY");
-        TestCase.assertEquals(correct, tester);
-        tester.fromString("");
-        TestCase.assertEquals(correct, tester);
-        tester.fromString("[]");
-        TestCase.assertEquals(correct, tester);
-
-        // ip_src
-        correct.setWildcards(~OFMatch.OFPFW_NW_SRC_MASK);
-        correct.setNetworkSource(0x01010203);
-        tester.fromString("nw_src=1.1.2.3");
-        TestCase.assertEquals(correct.getNetworkSourceMaskLen(), tester
-                .getNetworkSourceMaskLen());
-        TestCase.assertEquals(correct, tester);
-        tester.fromString("IP_sRc=1.1.2.3");
-        TestCase.assertEquals(correct.getNetworkSourceMaskLen(), tester
-                .getNetworkSourceMaskLen());
-        TestCase.assertEquals(correct, tester);
-        
-        // 0xVlan
-        correct = new OFMatch();
-        correct.setDataLayerVirtualLan((short)65535);
-        correct.setWildcards(~OFMatch.OFPFW_DL_VLAN);
-        tester = new OFMatch();
-        tester.fromString("dl_vlan=0xffff");
-        TestCase.assertEquals(correct, tester);
-        }
-
-    public void testToString() {
-        OFMatch match = new OFMatch();
-        match.fromString("nw_dst=3.4.5.6/8");
-        TestCase.assertEquals(8, match.getNetworkDestinationMaskLen());
-        String correct = "OFMatch[nw_dst=3.0.0.0/8]";
-        String tester = match.toString();
-
-        TestCase.assertEquals(correct, tester);
-        tester = "OFMatch[dl_type=35020]";
-        correct = "OFMatch[dl_type=0x88cc]";
-        match = new OFMatch();
-        match.fromString(tester);
-        TestCase.assertEquals(correct, match.toString());
-        OFMatch match2 = new OFMatch();
-        match2.fromString(correct);
-        TestCase.assertEquals(match, match2);
-    }
-
-    public void testClone() {
-        OFMatch match1 = new OFMatch();
-        OFMatch match2 = match1.clone();
-        TestCase.assertEquals(match1, match2);
-        match2.setNetworkProtocol((byte) 4);
-        match2.setWildcards(match2.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
-        TestCase.assertNotSame(match1, match2);
-    }
-
-    public void testIpToString() {
-        String test = OFMatch.ipToString(-1);
-        TestCase.assertEquals("255.255.255.255", test);
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java b/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java
deleted file mode 100644
index 60a9e732b..000000000
--- a/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-public class OFMessageContextStoreTest extends TestCase {
-    public void testStoreAndGet() {
-        OFMessage msg = new OFMessage();
-        OFMessageContextStore<String> store = new OFMessageContextStore<String>(msg, this.getName());
-        String key = "mykey";
-        String value = "myvalue";
-        store.put(key, value);
-        TestCase.assertEquals(value, store.get(key));
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFPacketOutTest.java b/src/test/java/org/openflow/protocol/OFPacketOutTest.java
deleted file mode 100644
index 55b54552f..000000000
--- a/src/test/java/org/openflow/protocol/OFPacketOutTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package org.openflow.protocol;
-
-import org.junit.Test;
-
-public class OFPacketOutTest {
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testBothBufferIdAndPayloadSet() {
-        OFPacketOut packetOut = new OFPacketOut();
-        packetOut.setBufferId(12);
-        packetOut.setPacketData(new byte[] { 1, 2, 3 });
-    }
-
-    @Test
-    public void testOnlyBufferIdSet() {
-        OFPacketOut packetOut = new OFPacketOut();
-        packetOut.setBufferId(12);
-        packetOut.setPacketData(null);
-        packetOut.setPacketData(new byte[] {});
-        packetOut.validate();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testNeitherBufferIdNorPayloadSet() {
-        OFPacketOut packetOut = new OFPacketOut();
-        packetOut.setBufferId(OFPacketOut.BUFFER_ID_NONE);
-        packetOut.setPacketData(null);
-        packetOut.validate();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testNeitherBufferIdNorPayloadSet2() {
-        OFPacketOut packetOut = new OFPacketOut();
-        packetOut.setBufferId(OFPacketOut.BUFFER_ID_NONE);
-        packetOut.setPacketData(new byte[] {});
-        packetOut.validate();
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testNeitherBufferIdNorPayloadSet3() {
-        OFPacketOut packetOut = new OFPacketOut();
-        packetOut.validate();
-    }
-
-}
diff --git a/src/test/java/org/openflow/protocol/OFPortConfigTest.java b/src/test/java/org/openflow/protocol/OFPortConfigTest.java
deleted file mode 100644
index 9b115ebc4..000000000
--- a/src/test/java/org/openflow/protocol/OFPortConfigTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.util.OFTestCase;
-
-public class OFPortConfigTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFPortMod msg = (OFPortMod) messageFactory
-                .getMessage(OFType.PORT_MOD);
-        msg.setHardwareAddress(new byte[6]);
-        msg.portNumber = 1;
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFType.PORT_MOD, msg.getType());
-        TestCase.assertEquals(1, msg.getPortNumber());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFPortStatusTest.java b/src/test/java/org/openflow/protocol/OFPortStatusTest.java
deleted file mode 100644
index 4fab64e03..000000000
--- a/src/test/java/org/openflow/protocol/OFPortStatusTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.OFPortStatus.OFPortReason;
-import org.openflow.util.OFTestCase;
-
-public class OFPortStatusTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFPortStatus msg = (OFPortStatus) messageFactory
-                .getMessage(OFType.PORT_STATUS);
-        msg.setDesc(new OFPhysicalPort());
-        msg.getDesc().setHardwareAddress(new byte[6]);
-        msg.getDesc().setName("eth0");
-        msg.setReason((byte) OFPortReason.OFPPR_ADD.ordinal());
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFType.PORT_STATUS, msg.getType());
-        TestCase.assertEquals((byte) OFPortReason.OFPPR_ADD.ordinal(), msg
-                .getReason());
-        TestCase.assertNotNull(msg.getDesc());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFSetConfigTest.java b/src/test/java/org/openflow/protocol/OFSetConfigTest.java
deleted file mode 100644
index 2a9e86f77..000000000
--- a/src/test/java/org/openflow/protocol/OFSetConfigTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.util.OFTestCase;
-
-public class OFSetConfigTest extends OFTestCase {
-    public void testWriteRead() throws Exception {
-        OFGetConfigReply msg = (OFGetConfigReply) messageFactory
-                .getMessage(OFType.GET_CONFIG_REPLY);
-        msg.setFlags((short) 1);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(OFType.GET_CONFIG_REPLY, msg.getType());
-        TestCase.assertEquals((short)1, msg.getFlags());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java b/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java
deleted file mode 100644
index 1885cae7b..000000000
--- a/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.factory.OFMessageFactory;
-import org.openflow.protocol.statistics.OFStatisticsType;
-import org.openflow.util.OFTestCase;
-
-public class OFStatisticsReplyTest extends OFTestCase {
-    public void testOFFlowStatisticsReply() throws Exception {
-        byte[] packet = new byte[] { 0x01, 0x11, 0x01, 0x2c, 0x00, 0x00, 0x00,
-                0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, (byte) 0xff,
-                (byte) 0xff, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00,
-                0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00, 0x00, 0x02, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, (byte) 0xa6,
-                (byte) 0xa6, 0x00, (byte) 0xff, (byte) 0xff, 0x00, 0x05, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                (byte) 0xc4, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00,
-                0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x02, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x08, 0x06,
-                0x00, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x03, 0x0a, 0x00,
-                0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x3b, 0x2f, (byte) 0xfa, 0x40, (byte) 0xff, (byte) 0xff, 0x00,
-                0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x01, 0x00,
-                0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x03, (byte) 0xff, (byte) 0xff, 0x00, 0x62, 0x08,
-                0x00, 0x00, 0x01, 0x62, 0x37, 0x0a, 0x00, 0x00, 0x02, 0x0a,
-                0x00, 0x00, 0x03, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x3a, (byte) 0xc5, 0x2a, (byte) 0x80, (byte) 0xff,
-                (byte) 0xff, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, (byte) 0xc4, 0x00, 0x00, 0x00,
-                0x08, 0x00, 0x02, 0x00, 0x00 };
-
-        OFMessageFactory factory = BasicFactory.getInstance();
-        ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet);
-        List<OFMessage> msg = factory.parseMessage(packetBuf);
-        TestCase.assertNotNull(msg);
-        TestCase.assertEquals(msg.size(), 1);
-        TestCase.assertTrue(msg.get(0) instanceof OFStatisticsReply);
-        OFStatisticsReply sr = (OFStatisticsReply) msg.get(0);
-        TestCase.assertEquals(OFStatisticsType.FLOW, sr.getStatisticType());
-        TestCase.assertEquals(3, sr.getStatistics().size());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java b/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java
deleted file mode 100644
index fceb8955e..000000000
--- a/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.factory.OFMessageFactory;
-import org.openflow.protocol.statistics.OFFlowStatisticsRequest;
-import org.openflow.protocol.statistics.OFStatisticsType;
-import org.openflow.protocol.statistics.OFVendorStatistics;
-import org.openflow.util.OFTestCase;
-
-public class OFStatisticsRequestTest extends OFTestCase {
-    public void testOFFlowStatisticsRequest() throws Exception {
-        byte[] packet = new byte[] { 0x01, 0x10, 0x00, 0x38, 0x00, 0x00, 0x00,
-                0x16, 0x00, 0x01, 0x00, 0x00, (byte) 0xff, (byte) 0xff,
-                (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                (byte) 0xff, 0x00, (byte) 0xff, (byte) 0xff };
-
-        OFMessageFactory factory = BasicFactory.getInstance();
-        ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet);
-        List<OFMessage> msg = factory.parseMessage(packetBuf);
-        TestCase.assertNotNull(msg);
-        TestCase.assertEquals(msg.size(), 1);
-        TestCase.assertTrue(msg.get(0) instanceof OFStatisticsRequest);
-        OFStatisticsRequest sr = (OFStatisticsRequest) msg.get(0);
-        TestCase.assertEquals(OFStatisticsType.FLOW, sr.getStatisticType());
-        TestCase.assertEquals(1, sr.getStatistics().size());
-        TestCase.assertTrue(sr.getStatistics().get(0) instanceof OFFlowStatisticsRequest);
-    }
-
-    public void testOFStatisticsRequestVendor() throws Exception {
-        byte[] packet = new byte[] { 0x01, 0x10, 0x00, 0x50, 0x00, 0x00, 0x00,
-                0x63, (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x4c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                0x01, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x20,
-                (byte) 0xe0, 0x00, 0x11, 0x00, 0x0c, 0x29, (byte) 0xc5,
-                (byte) 0x95, 0x57, 0x02, 0x25, 0x5c, (byte) 0xca, 0x00, 0x02,
-                (byte) 0xff, (byte) 0xff, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x50, 0x04,
-                0x00, 0x00, 0x00, 0x00, (byte) 0xff, 0x00, 0x00, 0x00,
-                (byte) 0xff, (byte) 0xff, 0x4e, 0x20 };
-
-        OFMessageFactory factory = BasicFactory.getInstance();
-        ChannelBuffer packetBuf = ChannelBuffers.wrappedBuffer(packet);
-        List<OFMessage> msg = factory.parseMessage(packetBuf);
-        TestCase.assertNotNull(msg);
-        TestCase.assertEquals(msg.size(), 1);
-        TestCase.assertTrue(msg.get(0) instanceof OFStatisticsRequest);
-        OFStatisticsRequest sr = (OFStatisticsRequest) msg.get(0);
-        TestCase.assertEquals(OFStatisticsType.VENDOR, sr.getStatisticType());
-        TestCase.assertEquals(1, sr.getStatistics().size());
-        TestCase.assertTrue(sr.getStatistics().get(0) instanceof OFVendorStatistics);
-        TestCase.assertEquals(68, ((OFVendorStatistics)sr.getStatistics().get(0)).getLength());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java b/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java
deleted file mode 100644
index d44ef7f8e..000000000
--- a/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-
-import junit.framework.TestCase;
-
-import org.junit.Test;
-import org.openflow.protocol.statistics.OFStatisticsType;
-
-
-public class OFStatisticsTypeTest extends TestCase {
-    @Test
-    public void testMapping() throws Exception {
-        TestCase.assertEquals(OFStatisticsType.DESC,
-                OFStatisticsType.valueOf((short) 0, OFType.STATS_REQUEST));
-        TestCase.assertEquals(OFStatisticsType.QUEUE,
-                OFStatisticsType.valueOf((short) 5, OFType.STATS_REQUEST));
-        TestCase.assertEquals(OFStatisticsType.VENDOR,
-                OFStatisticsType.valueOf((short) 0xffff, OFType.STATS_REQUEST));
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFTypeTest.java b/src/test/java/org/openflow/protocol/OFTypeTest.java
deleted file mode 100644
index c6bf0a347..000000000
--- a/src/test/java/org/openflow/protocol/OFTypeTest.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-
-import junit.framework.TestCase;
-
-import org.junit.Test;
-
-
-public class OFTypeTest extends TestCase {
-
-    public void testOFTypeCreate() throws Exception {
-        OFType foo = OFType.HELLO;
-        Class<? extends OFMessage> c = foo.toClass();
-        TestCase.assertEquals(c, OFHello.class);
-    }
-
-    @Test
-    public void testMapping() throws Exception {
-        TestCase.assertEquals(OFType.HELLO, OFType.valueOf((byte) 0));
-        TestCase.assertEquals(OFType.BARRIER_REPLY, OFType.valueOf((byte) 19));
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/OFVendorTest.java b/src/test/java/org/openflow/protocol/OFVendorTest.java
deleted file mode 100644
index c0385f441..000000000
--- a/src/test/java/org/openflow/protocol/OFVendorTest.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.protocol;
-
-import java.util.Arrays;
-
-import junit.framework.TestCase;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.vendor.OFByteArrayVendorData;
-import org.openflow.protocol.vendor.OFBasicVendorDataType;
-import org.openflow.protocol.vendor.OFBasicVendorId;
-import org.openflow.protocol.vendor.OFVendorData;
-import org.openflow.protocol.vendor.OFVendorId;
-import org.openflow.util.OFTestCase;
-
-public class OFVendorTest extends OFTestCase {
-
-    public static int ACME_VENDOR_ID = 0x00112233;
-    
-    static class AcmeVendorData implements OFVendorData {
-        protected int dataType;
-        
-        @Override
-        public int getLength() {
-            return 4;
-        }
-        
-        @Override
-        public void readFrom(ChannelBuffer data, int length) {
-            dataType = data.readInt();
-        }
-        
-        @Override
-        public void writeTo(ChannelBuffer data) {
-            data.writeInt(dataType);
-        }
-    }
-    
-    static class AcmeVendorData1 extends AcmeVendorData {
-        public short flags;
-        public short value;
-        
-        public static int DATA_TYPE = 1;
-        
-        public AcmeVendorData1() {
-        }
-        
-        public AcmeVendorData1(short flags, short value) {
-            this.dataType = DATA_TYPE;
-            this.flags = flags;
-            this.value = value;
-        }
-        
-        public short getFlags() {
-            return flags;
-        }
-        
-        public short getValue() {
-            return value;
-        }
-        
-        @Override
-        public int getLength() {
-            return 8;
-        }
-        
-        @Override
-        public void readFrom(ChannelBuffer data, int length) {
-            super.readFrom(data, length);
-            flags = data.readShort();
-            value = data.readShort();
-
-        }
-        @Override
-        public void writeTo(ChannelBuffer data) {
-            super.writeTo(data);
-            data.writeShort(flags);
-            data.writeShort(value);
-        }
-        
-        public static Instantiable<OFVendorData> getInstantiable() {
-            return new Instantiable<OFVendorData>() {
-                @Override
-                public OFVendorData instantiate() {
-                    return new AcmeVendorData1();
-                }
-            };
-        }
-    }
-    
-    static class AcmeVendorData2 extends AcmeVendorData {
-        public int type;
-        public int subtype;
-
-        public static int DATA_TYPE = 2;
-
-        public AcmeVendorData2() {
-        }
-        
-        public AcmeVendorData2(int type, int subtype) {
-            this.dataType = DATA_TYPE;
-            this.type = type;
-            this.subtype = subtype;
-        }
-        
-        public int getType() {
-            return type;
-        }
-        
-        public int getSubtype() {
-            return subtype;
-        }
-        
-        @Override
-        public int getLength() {
-            return 12;
-        }
-        
-        @Override
-        public void readFrom(ChannelBuffer data, int length) {
-            super.readFrom(data, length);
-            type = data.readShort();
-            subtype = data.readShort();
-
-        }
-        @Override
-        public void writeTo(ChannelBuffer data) {
-            super.writeTo(data);
-            data.writeShort(type);
-            data.writeShort(subtype);
-        }
-        
-        public static Instantiable<OFVendorData> getInstantiable() {
-            return new Instantiable<OFVendorData>() {
-                @Override
-                public OFVendorData instantiate() {
-                    return new AcmeVendorData2();
-                }
-            };
-        }
-    }
-    
-    {
-        OFBasicVendorId acmeVendorId = new OFBasicVendorId(ACME_VENDOR_ID, 4);
-        OFVendorId.registerVendorId(acmeVendorId);
-        OFBasicVendorDataType acmeVendorData1 = new OFBasicVendorDataType(
-            AcmeVendorData1.DATA_TYPE, AcmeVendorData1.getInstantiable());
-        acmeVendorId.registerVendorDataType(acmeVendorData1);
-        OFBasicVendorDataType acmeVendorData2 = new OFBasicVendorDataType(
-            AcmeVendorData2.DATA_TYPE, AcmeVendorData2.getInstantiable());
-        acmeVendorId.registerVendorDataType(acmeVendorData2);
-    }
-    
-    private OFVendor makeVendorMessage(int vendor) {
-        OFVendor msg = (OFVendor) messageFactory.getMessage(OFType.VENDOR);
-        msg.setVendorDataFactory(BasicFactory.getInstance());
-        msg.setVendor(vendor);
-        return msg;
-    }
-    
-    public void testWriteRead() throws Exception {
-        OFVendor msg = makeVendorMessage(1);
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        TestCase.assertEquals(1, msg.getVendor());
-    }
-    
-    public void testVendorData() throws Exception {
-        OFVendor msg = makeVendorMessage(ACME_VENDOR_ID);
-        OFVendorData vendorData = new AcmeVendorData1((short)11, (short)22);
-        msg.setVendorData(vendorData);
-        msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength());
-        ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        assertEquals(ACME_VENDOR_ID, msg.getVendor());
-        AcmeVendorData1 vendorData1 = (AcmeVendorData1) msg.getVendorData();
-        assertEquals(11, vendorData1.getFlags());
-        assertEquals(22, vendorData1.getValue());
-        
-        vendorData = new AcmeVendorData2(33, 44);
-        msg.setVendorData(vendorData);
-        msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength());
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        assertEquals(ACME_VENDOR_ID, msg.getVendor());
-        AcmeVendorData2 vendorData2 = (AcmeVendorData2) msg.getVendorData();
-        assertEquals(33, vendorData2.getType());
-        assertEquals(44, vendorData2.getSubtype());
-        
-        final int DUMMY_VENDOR_ID = 55;
-        msg.setVendor(DUMMY_VENDOR_ID);
-        byte[] genericVendorDataBytes = new byte[] {0x55, 0x66};
-        vendorData = new OFByteArrayVendorData(genericVendorDataBytes);
-        msg.setVendorData(vendorData);
-        msg.setLengthU(OFVendor.MINIMUM_LENGTH + vendorData.getLength());
-        bb.clear();
-        msg.writeTo(bb);
-        msg.readFrom(bb);
-        assertEquals(DUMMY_VENDOR_ID, msg.getVendor());
-        OFByteArrayVendorData genericVendorData = (OFByteArrayVendorData) msg.getVendorData();
-        assertTrue(Arrays.equals(genericVendorDataBytes, genericVendorData.getBytes()));
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/WildcardsTest.java b/src/test/java/org/openflow/protocol/WildcardsTest.java
deleted file mode 100644
index 5bf8d1231..000000000
--- a/src/test/java/org/openflow/protocol/WildcardsTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-package org.openflow.protocol;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.EnumSet;
-
-import org.junit.Test;
-import org.openflow.protocol.Wildcards.Flag;
-
-public class WildcardsTest {
-
-    @Test
-    public void testBasic() {
-        int[] intMasks = { 0, 0x3820e0, OFMatch.OFPFW_ALL_SANITIZED };
-        for (int i : intMasks) {
-            Wildcards w = Wildcards.of(i);
-            assertEquals(i, w.getInt());
-        }
-    }
-
-    @Test
-    public void testAllSanitize() {
-        Wildcards w = Wildcards.of(OFMatch.OFPFW_ALL);
-        assertEquals(OFMatch.OFPFW_ALL_SANITIZED, w.getInt());
-        assertTrue(w.isFull());
-        assertFalse(w.isExact());
-    }
-
-    @Test
-    public void testAll() {
-        Wildcards all = Wildcards.FULL;
-        assertTrue(all.isFull());
-        assertFalse(all.isExact());
-        assertEquals(0, all.getNwDstMask());
-        assertEquals(0, all.getNwSrcMask());
-
-        // unsetting flags from NONE is a no-op
-        Wildcards stillAll = all.wildcard(Flag.IN_PORT);
-        assertTrue(stillAll.isFull());
-        assertEquals(all, stillAll);
-
-        // so is setting a >= 32 netmask
-
-        stillAll = all.withNwSrcMask(0);
-        assertTrue(stillAll.isFull());
-        assertEquals(all, stillAll);
-
-        stillAll = all.withNwDstMask(0);
-        assertTrue(stillAll.isFull());
-        assertEquals(all, stillAll);
-    }
-
-    @Test
-    public void testNone() {
-        Wildcards none = Wildcards.EXACT;
-        assertTrue(none.isExact());
-        assertEquals(32, none.getNwDstMask());
-        assertEquals(32, none.getNwSrcMask());
-
-        // unsetting flags from NONE is a no-op
-        Wildcards stillNone = none.matchOn(Flag.IN_PORT);
-        assertTrue(stillNone.isExact());
-        assertEquals(none, stillNone);
-
-        // so is setting a >= 32 netmask
-        stillNone = none.withNwSrcMask(32);
-        assertTrue(stillNone.isExact());
-        assertEquals(none, stillNone);
-
-        stillNone = none.withNwDstMask(32);
-        assertTrue(stillNone.isExact());
-        assertEquals(none, stillNone);
-    }
-
-    @Test
-    public void testSetOneFlag() {
-        Wildcards none = Wildcards.EXACT;
-        assertTrue(none.isExact());
-        assertFalse(none.isWildcarded(Flag.DL_SRC));
-        Wildcards one = none.wildcard(Flag.DL_SRC);
-        assertFalse(one.isExact());
-        assertTrue(one.isWildcarded(Flag.DL_SRC));
-        assertEquals(OFMatch.OFPFW_DL_SRC, one.getInt());
-        assertEquals(EnumSet.of(Flag.DL_SRC), one.getWildcardedFlags());
-    }
-
-    @Test
-    public void testSetTwoFlags() {
-        Wildcards none = Wildcards.EXACT;
-
-        // set two flags
-        Wildcards two = none.wildcard(Flag.DL_SRC, Flag.DL_DST);
-        assertFalse(two.isExact());
-        assertTrue(two.isWildcarded(Flag.DL_SRC));
-        assertTrue(two.isWildcarded(Flag.DL_DST));
-        assertEquals(OFMatch.OFPFW_DL_SRC | OFMatch.OFPFW_DL_DST, two.getInt());
-        assertEquals(EnumSet.of(Flag.DL_SRC, Flag.DL_DST), two.getWildcardedFlags());
-
-        // unset dl_dst
-        Wildcards gone = two.matchOn(Flag.DL_DST);
-        assertFalse(gone.isExact());
-        assertTrue(gone.isWildcarded(Flag.DL_SRC));
-        assertFalse(gone.isWildcarded(Flag.DL_DST));
-        assertEquals(OFMatch.OFPFW_DL_SRC, gone.getInt());
-        assertEquals(EnumSet.of(Flag.DL_SRC), gone.getWildcardedFlags());
-    }
-
-    @Test
-    public void testSetNwSrc() {
-        Wildcards none = Wildcards.EXACT;
-        assertEquals(32, none.getNwSrcMask());
-
-        // unsetting flags from NONE is a no-op
-        Wildcards nwSet = none.withNwSrcMask(8);
-        assertFalse(nwSet.isExact());
-        assertEquals(EnumSet.noneOf(Flag.class), nwSet.getWildcardedFlags());
-        assertEquals(8, nwSet.getNwSrcMask());
-        assertEquals((32 - 8) << OFMatch.OFPFW_NW_SRC_SHIFT, nwSet.getInt());
-    }
-
-    @Test
-    public void testSetNwDst() {
-        Wildcards none = Wildcards.EXACT;
-        assertEquals(32, none.getNwDstMask());
-
-        // unsetting flags from NONE is a no-op
-        Wildcards nwSet = none.withNwDstMask(8);
-        assertFalse(nwSet.isExact());
-        assertEquals(EnumSet.noneOf(Flag.class), nwSet.getWildcardedFlags());
-        assertEquals(8, nwSet.getNwDstMask());
-        assertEquals((32 - 8) << OFMatch.OFPFW_NW_DST_SHIFT, nwSet.getInt());
-    }
-
-    @Test
-    public void testToString() {
-        String s = Wildcards.FULL.toString();
-        assertNotNull(s);
-        assertTrue(s.length() > 0);
-    }
-
-    @Test
-    public void testInvert() {
-        assertEquals(Wildcards.FULL, Wildcards.EXACT.inverted());
-
-        Wildcards some = Wildcards.of(Flag.DL_VLAN, Flag.DL_VLAN_PCP);
-        Wildcards inv = some.inverted();
-
-        for(Flag f : Flag.values()) {
-            boolean shouldBeSet = (f == Flag.DL_VLAN || f == Flag.DL_VLAN_PCP);
-
-            assertEquals("Flag " + f + " "
-                         + (shouldBeSet ? "should be set " : "should not be set"),
-                    shouldBeSet, some.isWildcarded(f));
-            assertEquals(!(f == Flag.DL_VLAN || f == Flag.DL_VLAN_PCP), inv.isWildcarded(f));
-        }
-        assertEquals(0, inv.getNwDstMask());
-        assertEquals(0, inv.getNwSrcMask());
-    }
-}
diff --git a/src/test/java/org/openflow/protocol/action/MockVendorAction.java b/src/test/java/org/openflow/protocol/action/MockVendorAction.java
deleted file mode 100644
index 49b69fb81..000000000
--- a/src/test/java/org/openflow/protocol/action/MockVendorAction.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.openflow.protocol.action;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-
-
-public class MockVendorAction extends OFActionVendor {
-    public static final int VENDOR_ID = 0xdeadbeef;
-
-    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
-    private byte[] mockData;
-
-    public byte[] getMockData() {
-        return mockData;
-    }
-
-    public void setMockData(byte[] mockData) {
-        this.mockData = mockData;
-    }
-
-    @Override
-    public void readFrom(ChannelBuffer data) {
-        super.readFrom(data);
-
-        int dataLength = getLength() - MINIMUM_LENGTH;
-        if(dataLength > 0) {
-            mockData = new byte[dataLength];
-            data.readBytes(mockData);
-        } else {
-            mockData = EMPTY_BYTE_ARRAY;
-        }
-
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer data) {
-        super.writeTo(data);
-        data.writeBytes(mockData);
-    }
-
-
-}
diff --git a/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java b/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java
deleted file mode 100644
index bbc254ca0..000000000
--- a/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package org.openflow.protocol.action;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.openflow.protocol.factory.OFVendorActionFactory;
-
-public class MockVendorActionFactory implements OFVendorActionFactory {
-
-    @Override
-    public OFActionVendor readFrom(ChannelBuffer data) {
-        MockVendorAction action = new MockVendorAction();
-        action.readFrom(data);
-        return action;
-    }
-
-}
diff --git a/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java b/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java
deleted file mode 100644
index 31ad675d6..000000000
--- a/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.openflow.protocol.action;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-import org.openflow.protocol.factory.OFVendorActionRegistry;
-
-public class OFVendorActionRegistryTest {
-
-    @Test
-    public void test() {
-        MockVendorActionFactory factory = new MockVendorActionFactory();
-        OFVendorActionRegistry.getInstance().register(MockVendorAction.VENDOR_ID, factory);
-        assertEquals(factory, OFVendorActionRegistry.getInstance().get(MockVendorAction.VENDOR_ID));
-    }
-
-}
diff --git a/src/test/java/org/openflow/util/HexStringTest.java b/src/test/java/org/openflow/util/HexStringTest.java
deleted file mode 100644
index a8f8ba4b8..000000000
--- a/src/test/java/org/openflow/util/HexStringTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import org.junit.Test;
-
-import junit.framework.TestCase;
-
-/**
- * Does hexstring conversion work?
- * 
- * @author Rob Sherwood (rob.sherwood@stanford.edu)
- * 
- */
-
-public class HexStringTest extends TestCase {
-    
-    @Test
-    public void testMarshalling() throws Exception {
-        String dpidStr = "00:00:00:23:20:2d:16:71";
-        long dpid = HexString.toLong(dpidStr);
-        String testStr = HexString.toHexString(dpid);
-        TestCase.assertEquals(dpidStr, testStr);
-    }
-    
-    @Test
-    public void testToLong() {
-        String dpidStr = "3e:1f:01:fc:72:8c:63:31";
-        long valid = 0x3e1f01fc728c6331L;
-        long testLong = HexString.toLong(dpidStr);
-        TestCase.assertEquals(valid, testLong);
-    }
-    
-    @Test
-    public void testToLongMSB() {
-        String dpidStr = "ca:7c:5e:d1:64:7a:95:9b";
-        long valid = -3856102927509056101L;
-        long testLong = HexString.toLong(dpidStr);
-        TestCase.assertEquals(valid, testLong);
-    }
-    
-    @Test
-    public void testToLongError() {
-        String dpidStr = "09:08:07:06:05:04:03:02:01";
-        try {
-            HexString.toLong(dpidStr);
-            fail("HexString.toLong() should have thrown a NumberFormatException");
-        }
-        catch (NumberFormatException expected) {
-            // do nothing
-        }
-    }
-
-    @Test
-    public void testToStringBytes() {
-        byte[] dpid = { 0, 0, 0, 0, 0, 0, 0, -1 };
-        String valid = "00:00:00:00:00:00:00:ff";
-        String testString = HexString.toHexString(dpid);
-        TestCase.assertEquals(valid, testString);
-    }
-    
-    @Test
-    public void testFromHexStringError() {
-        String invalidStr = "00:00:00:00:00:00:ffff";
-        try {
-            HexString.fromHexString(invalidStr);
-            fail("HexString.fromHexString() should have thrown a NumberFormatException");
-        }
-        catch (NumberFormatException expected) {
-            // do nothing
-        }
-    }
-}
diff --git a/src/test/java/org/openflow/util/OFTestCase.java b/src/test/java/org/openflow/util/OFTestCase.java
deleted file mode 100644
index 07bee2d58..000000000
--- a/src/test/java/org/openflow/util/OFTestCase.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import org.openflow.protocol.factory.BasicFactory;
-import org.openflow.protocol.factory.OFMessageFactory;
-
-import junit.framework.TestCase;
-
-public class OFTestCase extends TestCase {
-    public OFMessageFactory messageFactory;
-    
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        messageFactory = BasicFactory.getInstance();
-    }
-
-    public void test() throws Exception {
-    }
-}
diff --git a/src/test/java/org/openflow/util/U16Test.java b/src/test/java/org/openflow/util/U16Test.java
deleted file mode 100644
index ba87e7b12..000000000
--- a/src/test/java/org/openflow/util/U16Test.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import junit.framework.TestCase;
-
-public class U16Test extends TestCase {
-  /**
-   * Tests that we correctly translate unsigned values in and out of a short
-   * @throws Exception
-   */
-  public void test() throws Exception {
-      int val = 0xffff;
-      TestCase.assertEquals((short)-1, U16.t(val));
-      TestCase.assertEquals((short)32767, U16.t(0x7fff));
-      TestCase.assertEquals(val, U16.f((short)-1));
-  }
-}
diff --git a/src/test/java/org/openflow/util/U32Test.java b/src/test/java/org/openflow/util/U32Test.java
deleted file mode 100644
index 223c1034e..000000000
--- a/src/test/java/org/openflow/util/U32Test.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import junit.framework.TestCase;
-
-public class U32Test extends TestCase {
-  /**
-   * Tests that we correctly translate unsigned values in and out of an int
-   * @throws Exception
-   */
-  public void test() throws Exception {
-      long val = 0xffffffffL;
-      TestCase.assertEquals(-1, U32.t(val));
-      TestCase.assertEquals(val, U32.f(-1));
-  }
-}
diff --git a/src/test/java/org/openflow/util/U64Test.java b/src/test/java/org/openflow/util/U64Test.java
deleted file mode 100644
index 0a97e302f..000000000
--- a/src/test/java/org/openflow/util/U64Test.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import java.math.BigInteger;
-
-import junit.framework.TestCase;
-
-public class U64Test extends TestCase {
-  /**
-   * Tests that we correctly translate unsigned values in and out of a long
-   * @throws Exception
-   */
-  public void test() throws Exception {
-      BigInteger val = new BigInteger("ffffffffffffffff", 16);
-      TestCase.assertEquals(-1, U64.t(val));
-      TestCase.assertEquals(val, U64.f(-1));
-  }
-}
diff --git a/src/test/java/org/openflow/util/U8Test.java b/src/test/java/org/openflow/util/U8Test.java
deleted file mode 100644
index 2c06c4db3..000000000
--- a/src/test/java/org/openflow/util/U8Test.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import junit.framework.TestCase;
-
-public class U8Test extends TestCase {
-  /**
-   * Tests that we correctly translate unsigned values in and out of a byte
-   * @throws Exception
-   */
-  public void test() throws Exception {
-      short val = 0xff;
-      TestCase.assertEquals(-1, U8.t(val));
-      TestCase.assertEquals(val, U8.f((byte)-1));
-  }
-}
diff --git a/src/test/java/org/openflow/util/UnsignedTest.java b/src/test/java/org/openflow/util/UnsignedTest.java
deleted file mode 100644
index 7cdf7391b..000000000
--- a/src/test/java/org/openflow/util/UnsignedTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
-*    Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
-*    University
-* 
-*    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 org.openflow.util;
-
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-
-import junit.framework.TestCase;
-
-public class UnsignedTest extends TestCase {
-    public static String ULONG_MAX = "18446744073709551615";
-
-  /**
-   * Tests that we correctly extract an unsigned long into a BigInteger
-   * @throws Exception
-   */
-  public void testGetUnsignedLong() throws Exception {
-    ByteBuffer bb = ByteBuffer.allocate(8);
-    bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff);
-    bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff);
-    bb.position(0);
-    bb.limit(8);
-    BigInteger bi = Unsigned.getUnsignedLong(bb);
-    BigInteger uLongMax = new BigInteger(ULONG_MAX);
-    for (int i = 0; i < uLongMax.bitCount(); ++i) {
-        TestCase.assertTrue("Bit: " + i + " should be: " + uLongMax.testBit(i),
-                uLongMax.testBit(i) == bi.testBit(i));
-    }
-    TestCase.assertEquals(ULONG_MAX, bi.toString());
-
-    bb = ByteBuffer.allocate(10);
-    bb.put((byte)0x00);
-    bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff);
-    bb.put((byte)0xff).put((byte)0xff).put((byte)0xff).put((byte)0xff);
-    bb.put((byte)0x00);
-    bb.position(0);
-    bb.limit(10);
-    bi = Unsigned.getUnsignedLong(bb, 1);
-    uLongMax = new BigInteger(ULONG_MAX);
-    for (int i = 0; i < uLongMax.bitCount(); ++i) {
-        TestCase.assertTrue("Bit: " + i + " should be: " + uLongMax.testBit(i),
-                uLongMax.testBit(i) == bi.testBit(i));
-    }
-    TestCase.assertEquals(ULONG_MAX, bi.toString());
-  }
-
-  /**
-   * Tests that we correctly put an unsigned long into a ByteBuffer
-   * @throws Exception
-   */
-  public void testPutUnsignedLong() throws Exception {
-    ByteBuffer bb = ByteBuffer.allocate(8);
-    BigInteger uLongMax = new BigInteger(ULONG_MAX);
-    Unsigned.putUnsignedLong(bb, uLongMax);
-    for (int i = 0; i < 8; ++i) {
-        TestCase.assertTrue("Byte: " + i + " should be 0xff, was: " + bb.get(i),
-                (bb.get(i) & (short)0xff) == 0xff);
-    }
-
-    bb = ByteBuffer.allocate(10);
-    Unsigned.putUnsignedLong(bb, uLongMax, 1);
-    int offset = 1;
-    for (int i = 0; i < 8; ++i) {
-        TestCase.assertTrue("Byte: " + i + " should be 0xff, was: " +
-                bb.get(offset+i), (bb.get(offset+i) & (short)0xff) == 0xff);
-    }
-  }
-}
-- 
GitLab