Adding broken version of netty-fied openflowj and openflow protocol plugin 77/877/3
authorColin Dixon <ckd@us.ibm.com>
Wed, 14 Aug 2013 18:40:50 +0000 (13:40 -0500)
committerColin Dixon <ckd@us.ibm.com>
Mon, 19 Aug 2013 20:11:11 +0000 (15:11 -0500)
Contributes two bundles:
1.) openflowj_netty: openflowj which is designed to use the netty
    asynchronous i/o library
2.) openflow_netty: an openflow protocol plugin that is designed to use
    the netty version of openflowj

There is still work that needs to be done on at least two fronts:
1.) The bundles are designed work in the context of being directly in
    the main controller repo and so their pom.xml files need to be
    reworked and there probably needs to be a distribution directory
    which pulls things together.
2.) Even when they are combined, currently they have some bugs which
    cause a long series of exceptions to be thrown when a mininet
    pingall is done. I assume that this should be easy to hunt down,
    but I'm not certain.

Signed-off-by: Colin Dixon <ckd@us.ibm.com>
Change-Id: Ifdc8a6c065bc2cdda62114d4356bb91a1b6b3b2c

155 files changed:
openflow_netty/pom.xml [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/IEnhancedSwitch.java [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/EnhancedController.java [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/EnhancedSwitchHandler.java [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFChannelState.java [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFMessageDecoder.java [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFMessageEncoder.java [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OpenflowPipelineFactory.java [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/TrafficStatisticsHandler.java [new file with mode: 0644]
openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/EnhancedActivator.java [new file with mode: 0644]
third-party/commons/thirdparty/pom.xml [new file with mode: 0644]
third-party/openflowj_netty/LICENSE [new file with mode: 0644]
third-party/openflowj_netty/Makefile [new file with mode: 0644]
third-party/openflowj_netty/README [new file with mode: 0644]
third-party/openflowj_netty/eclipse_codestyle.xml [new file with mode: 0644]
third-party/openflowj_netty/lib/commons-cli-1.2.jar [new file with mode: 0644]
third-party/openflowj_netty/lib/junit-4.8.1.jar [new file with mode: 0644]
third-party/openflowj_netty/pom.xml [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/Instantiable.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFBarrierReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFBarrierRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFEchoReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFEchoRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFError.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFeaturesReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFeaturesRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFlowMod.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFlowRemoved.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFGetConfigReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFGetConfigRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFHello.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatch.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMessage.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMessageContextStore.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketIn.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketOut.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketQueue.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPhysicalPort.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPort.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPortMod.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPortStatus.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueProp.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFSetConfig.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFSwitchConfig.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFType.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFVendor.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/Wildcards.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFAction.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionOutput.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionType.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVendor.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/BasicFactory.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/MessageParseException.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFActionFactory.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFStatistics.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorId.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/HexString.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/IProducer.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/LRULinkedHashMap.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/ProducerConsumer.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/StringByteSerializer.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/U16.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/U32.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/U64.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/U8.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/util/Unsigned.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/BasicFactoryTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFActionTypeTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFErrorTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFMatchTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPacketOutTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPortConfigTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPortStatusTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFSetConfigTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFTypeTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFVendorTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/WildcardsTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/MockVendorAction.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/util/HexStringTest.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/util/OFTestCase.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/util/U16Test.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/util/U32Test.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/util/U64Test.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/util/U8Test.java [new file with mode: 0644]
third-party/openflowj_netty/src/test/java/org/openflow/util/UnsignedTest.java [new file with mode: 0644]

diff --git a/openflow_netty/pom.xml b/openflow_netty/pom.xml
new file mode 100644 (file)
index 0000000..970e150
--- /dev/null
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+  <artifactId>protocol_plugins.openflow_netty</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>
+              org.opendaylight.controller.sal.packet,
+              org.opendaylight.controller.sal.action,
+              org.opendaylight.controller.sal.connection,
+              org.opendaylight.controller.sal.discovery,
+              org.opendaylight.controller.sal.topology,
+              org.opendaylight.controller.sal.core,
+              org.opendaylight.controller.sal.flowprogrammer,
+              org.opendaylight.controller.sal.reader,
+              org.opendaylight.controller.sal.inventory,
+              org.opendaylight.controller.sal.match,
+              org.opendaylight.controller.sal.utils,
+              org.apache.commons.lang3.builder,
+              org.apache.commons.lang3.tuple,
+              org.apache.felix.dm,
+              org.slf4j,
+              org.eclipse.osgi.framework.console,
+              org.osgi.framework,
+              javax.net.ssl,
+              org.jboss.netty.*
+            </Import-Package>
+            <Export-Package>
+              org.opendaylight.controller.protocol_plugin.openflow.core.internal;-split-package:=merge-first,
+              org.opendaylight.controller.protocol_plugin.openflow.core;-split-package:=merge-first,
+            </Export-Package>
+            <Embed-Dependency>
+              org.openflow.openflowj_netty,org.jboss.netty;protocol_plugins.openflow;type=!pom;inline=false
+            </Embed-Dependency>
+            <Embed-Transitive>
+              false
+            </Embed-Transitive>
+            <Bundle-Activator>
+              org.opendaylight.controller.protocol_plugin.openflow.internal.EnhancedActivator
+            </Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.5.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal.connection</artifactId>
+      <version>0.1.0-SNAPSHOT</version>
+    </dependency>
+    <!-- Make sure this comes before protocol_plugins.openflow Maven
+         honors the classpath order to reliable builds and here we
+         want to make sure that the openflowJ embedded is picking the
+         netty one over the non-netty enabled-->
+    <dependency>
+      <groupId>org.opendaylight.controller.thirdparty</groupId>
+      <artifactId>org.openflow.openflowj_netty</artifactId>
+      <version>1.0.2-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>protocol_plugins.openflow</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.netty</groupId>
+      <artifactId>netty</artifactId>
+      <version>3.2.6.Final</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/IEnhancedSwitch.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/IEnhancedSwitch.java
new file mode 100644 (file)
index 0000000..954f92a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.protocol_plugin.openflow.core;
+
+import java.net.SocketAddress;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.protocol.OFStatisticsRequest;
+
+/**
+ * This interface defines an abstraction of an Open Flow Switch.
+ *
+ */
+public interface IEnhancedSwitch extends ISwitch {
+    public void startHandler();
+
+    public void shutDownHandler();
+
+    public void handleMessage(OFMessage ofMessage);
+
+    public void flushBufferedMessages();
+
+    public SocketAddress getRemoteAddress();
+
+    public SocketAddress getLocalAddress();
+}
diff --git a/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/EnhancedController.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/EnhancedController.java
new file mode 100644 (file)
index 0000000..53f2d9f
--- /dev/null
@@ -0,0 +1,674 @@
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.RejectedExecutionException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SocketChannel;
+
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.AdaptiveReceiveBufferSizePredictorFactory;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+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.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.jboss.netty.handler.execution.ExecutionHandler;
+import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
+import org.jboss.netty.handler.timeout.IdleStateAwareChannelUpstreamHandler;
+import org.jboss.netty.handler.timeout.IdleStateEvent;
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.ObjectSizeEstimator;
+import org.jboss.netty.handler.timeout.ReadTimeoutException;
+
+
+
+
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.MessageParseException;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IController;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IEnhancedSwitch;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IMessageListener;
+import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
+import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitchStateListener;
+import org.opendaylight.controller.sal.connection.ConnectionConstants;
+import org.opendaylight.controller.sal.connection.IPluginInConnectionService;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+//import org.opendaylight.controller.protocol_plugin.openflow.core.internal.OFChannelState.HandshakeState;
+//import org.openflow.protocol.OFType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+
+public class EnhancedController implements IController, IPluginInConnectionService {
+
+
+    protected BasicFactory factory;
+
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(EnhancedController.class);
+
+
+    // Track connected switches via SwitchID
+    private ConcurrentHashMap<Long, ISwitch> connectedSwitches;
+
+    // Track connected switches via ChannelID. Whenever the message
+    private ConcurrentHashMap<Integer, IEnhancedSwitch> channelIDToSwitchMap;
+
+    // only 1 message listener per OFType
+    private ConcurrentMap<OFType, IMessageListener> messageListeners;
+
+    // only 1 switch state listener
+    private ISwitchStateListener switchStateListener;
+    private AtomicInteger switchInstanceNumber;
+
+
+    private OFChannelHandler ofChannelHandler = null;
+    private ControllerServerBootstrap bootstrap = null;
+
+    private ThreadPoolExecutor execHandler = null;
+
+    private static final int SEND_BUFFER_SIZE = 1 * 1024 * 1024;
+    private static final int RECEIVE_BUFFER_SIZE = 1 * 1024 * 1024;
+    private static final int WRITE_BUFFER_LOW_WATERMARK = 32 * 1024;
+    private static final int WRITE_BUFFER_HIGH_WATERMARK = 64 * 1024;
+    private static final String CONTROLLER_HOST = null;
+    private static final int CONTROLLER_PORT = 6633;
+
+    private static final int OMATPE_CORE_POOL_SIZE = 200;
+    private static final int OMATPE_PER_CHANNEL_SIZE = 2 * 1048576;
+    private static final int OMATPE_POOL_WIDE_SIZE = 0; //1073741824;
+    private static final int OMATPE_THREAD_KEEP_ALIVE_IN_MILLISECONDS = 100;
+    private static final int EXPERIMENTAL_OMATPE_OBJECT_SIZE = 1000; // bytes
+
+    private HashedWheelTimer hashedWheelTimer = null;
+
+    // This executor would be used by individual switches to handle
+    // cases like Stats Request/Response or Sync* methods which sends request and
+    // waits via Future for responses. Please note that threads in this
+    // pool are shared across multiple threads. So, if all threads are busy,
+    // Socket IO thread would get blocked creating sharp decline in performance
+    // If possible TOTALLY avoid any thread usage which does network level
+    // request / response by making a thread in this pool wait for response
+    // Consider storing the Future reference against the "sent" request and
+    // fire-event to wake-up the same when response is received rather than making the
+    // sender thread getting into a "wait" mode. That would never scale
+    private ExecutorService executorService = null;
+
+    // IMPORTANT: DO NOT REDUCE THIS THREAD COUNT TO 0
+    // THIS THREAD COUNT WOULD BE USED FOR SOCKET-IO + FOLLOWING EXECUTION CHAIN
+    // Plugin + SAL + North-to-SAL + Egress (flow_provisioning)
+    private static final int WORKER_THREAD_COUNT = 4;
+
+    // This is a handy thread-pool if WORKER_THREAD_COUNT is not able to cope with
+    // Socket IO + Execution of the following handling chain
+    // Plugin + SAL + North-to-SAL + Egress (flow_provisioning)
+    private static final int EXECUTION_HANDLER_THREAD_POOL_SIZE = 0;
+
+    // This is the thread-pool which can be optionally used for
+    // building synchronous semantics for flow_mod and stats handling cycle
+    // Flow_Mod in synchronous model could involve FLOW_MOD + BARRIER_MSG
+    // sending and receiving with wait timeout for reply
+    // Stats handling in synchronous model could involve STATS_REQUEST + STATS_REPLY
+    // sending and receiving with wait timeout for reply
+    private static final int THREAD_POOL_SIZE_FOR_EGRESS_SYNC_MSGS = 30;
+
+    private TrafficStatisticsHandler statsHandler = null;
+
+    // Lock for locking messagelisteners list while escalating the switch
+    // messages
+    private ReentrantLock lock = new ReentrantLock();
+
+    private static final int FLUSH_BATCH_SIZE = 100;
+
+    //****************** IController Interafce Methods Begin ******************
+
+    @Override
+    public void addMessageListener(OFType type, IMessageListener listener) {
+        IMessageListener currentListener = this.messageListeners.get(type);
+        if (currentListener != null) {
+            logger.warn("{} is already listened by {}", type.toString(),
+                    currentListener.toString());
+        }
+        this.messageListeners.put(type, listener);
+        logger.debug("{} is now listened by {}", type.toString(),
+                listener.toString());
+
+    }
+
+    @Override
+    public void removeMessageListener(OFType type, IMessageListener listener) {
+        IMessageListener currentListener = this.messageListeners.get(type);
+        if ((currentListener != null) && (currentListener == listener)) {
+            logger.debug("{} listener {} is Removed", type.toString(),
+                    listener.toString());
+            this.messageListeners.remove(type);
+        }
+
+    }
+
+    @Override
+    public void addSwitchStateListener(ISwitchStateListener listener) {
+        if (this.switchStateListener != null) {
+            logger.warn("Switch events are already listened by {}",
+                    this.switchStateListener.toString());
+        }
+        this.switchStateListener = listener;
+        logger.debug("Switch events are now listened by {}",
+                listener.toString());
+
+    }
+
+    @Override
+    public void removeSwitchStateListener(ISwitchStateListener listener) {
+        if ((this.switchStateListener != null)
+                && (this.switchStateListener == listener)) {
+            logger.debug("SwitchStateListener {} is Removed",
+                    listener.toString());
+            this.switchStateListener = null;
+        }
+
+    }
+
+    @Override
+    public Map<Long, ISwitch> getSwitches() {
+        return this.connectedSwitches;
+    }
+
+    @Override
+    public ISwitch getSwitch(Long switchId) {
+        return this.connectedSwitches.get(switchId);
+    }
+
+    //****************** IController Interafce Methods End ******************
+
+
+
+    //****************** Dependency-manager callbacks Begin ******************
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    public void init() {
+        logger.debug("Initializing!");
+        this.connectedSwitches = new ConcurrentHashMap<Long, ISwitch>();
+        this.channelIDToSwitchMap = new ConcurrentHashMap<Integer, IEnhancedSwitch>();
+        this.messageListeners = new ConcurrentHashMap<OFType, IMessageListener>();
+        this.switchStateListener = null;
+        this.hashedWheelTimer = new HashedWheelTimer();
+        this.statsHandler = new TrafficStatisticsHandler(hashedWheelTimer);
+        this.switchInstanceNumber = new AtomicInteger(0);
+        this.factory = new BasicFactory();
+        this.bootstrap = new ControllerServerBootstrap(this);
+        this.executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE_FOR_EGRESS_SYNC_MSGS);
+
+
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called and after
+     * the services provided by the class are registered in the service registry
+     *
+     */
+    public void start() {
+        this.statsHandler.init();
+        logger.debug("Starting!");
+        bootstrap.startServer(WORKER_THREAD_COUNT,
+                CONTROLLER_HOST,
+                CONTROLLER_PORT,
+                ofChannelHandler);
+
+
+    }
+
+    /**
+     * Function called by the dependency manager before the services exported by
+     * the component are unregistered, this will be followed by a "destroy ()"
+     * calls
+     *
+     */
+    public void stop() {
+        for (Iterator<Entry<Integer, IEnhancedSwitch>> it = channelIDToSwitchMap.entrySet().iterator(); it
+                .hasNext();) {
+            Entry<Integer, IEnhancedSwitch> entry = it.next();
+            ((EnhancedSwitchHandler) entry.getValue()).stop();
+        }
+
+        hashedWheelTimer.stop();
+
+        executorService.shutdown();
+    }
+
+    /**
+     * Function called by the dependency manager when at least one dependency
+     * become unsatisfied or when the component is shutting down because for
+     * example bundle is being stopped.
+     *
+     */
+    public void destroy() {
+    }
+    //****************** Dependency-manager callbacks End ******************
+
+
+
+    public OFChannelHandler getChannelHandler(){
+        return new OFChannelHandler(this);
+    }
+
+
+    protected class OFChannelHandler extends IdleStateAwareChannelUpstreamHandler{
+
+
+        protected EnhancedController controller = null;
+        protected Channel channel = null;
+
+
+        public OFChannelHandler(EnhancedController controller){
+            this.controller = controller;
+        }
+
+
+        @Override
+        public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
+                throws Exception {
+            List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+            msglist.add(factory.getMessage(OFType.ECHO_REQUEST));
+            e.getChannel().write(msglist);
+            statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ECHO_REQUEST_SENT);
+        }
+
+        @Override
+        public void channelConnected(ChannelHandlerContext ctx,
+                ChannelStateEvent e) throws Exception {
+            channel = e.getChannel();
+            logger.info("New switch connection from {}",
+                     channel.getRemoteAddress());
+
+            Integer channelID = e.getChannel().getId();
+
+            IEnhancedSwitch switchHandler = new EnhancedSwitchHandler(controller,
+                    channelID, channel, hashedWheelTimer, executorService, statsHandler);
+            switchHandler.startHandler();
+            channelIDToSwitchMap.put(channelID, switchHandler);
+            statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.CONNECTED_SWITCHES);
+
+          }
+
+        @Override
+        public void channelDisconnected(ChannelHandlerContext ctx,
+                ChannelStateEvent e) throws Exception {
+            // when SwitchHandler.shutDownHandler is called, Controller would
+            // get the feedback via switchDeleted method. So that both SwitchHandler and
+            // controller both release resources of the switch concerned
+
+            Integer channelID = e.getChannel().getId();
+            IEnhancedSwitch switchHandler = channelIDToSwitchMap.get(channelID);
+            if (switchHandler != null){
+                switchHandler.shutDownHandler();
+            }
+            statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.DISCONNECTED_SWITCHES);
+
+        }
+
+        @Override
+        public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
+                throws Exception {
+
+            EnhancedSwitchHandler sw = null;
+
+            if (e.getCause() instanceof ReadTimeoutException) {
+                // switch timeout
+                logger.error("Disconnecting switch {} due to read timeout",
+                        e.getChannel().getId(), e.getCause().getMessage());
+                ctx.getChannel().close();
+                sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+                sw.stop();
+            /*
+            } else if (e.getCause() instanceof HandshakeTimeoutException) {
+                logger.error("Disconnecting switch {}: failed to complete handshake",
+                        e.getChannel().getId());
+                ctx.getChannel().close();
+                channelIDToSwitchMap.remove(e.getChannel().getId());
+                */
+            } else if (e.getCause() instanceof ClosedChannelException) {
+                logger.warn("Channel for sw {} already closed Error : {}",
+                        e.getChannel().getId(), e.getCause().getMessage());
+                ctx.getChannel().close();
+                sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+                sw.stop();
+            } else if (e.getCause() instanceof IOException) {
+                logger.error("Disconnecting switch {} due to IO Error: {}",
+                        e.getChannel().getId(), e.getCause().getMessage());
+                ctx.getChannel().close();
+                sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+                sw.stop();
+            /*
+            } else if (e.getCause() instanceof SwitchStateException) {
+                logger.error("Disconnecting switch {} due to switch state error: {}",
+                        e.getChannel().getId(), e.getCause().getMessage());
+                ctx.getChannel().close();
+                channelIDToSwitchMap.remove(e.getChannel().getId());
+
+            } else if (e.getCause() instanceof MessageParseException) {
+                logger.error("Disconnecting switch {} due to message parse error Error : {}",
+                        e.getChannel().getId(), e.getCause().getMessage());
+                ctx.getChannel().close();
+                sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+                sw.stop(); */
+            } else if (e.getCause() instanceof RejectedExecutionException) {
+                logger.warn("Could not process message: queue full");
+                ctx.getChannel().close();
+                sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+                sw.stop();
+            } else {
+                logger.error("Error while processing message from switch {} Error : {}",
+                        e.getChannel().getId(), e.getCause().getMessage());
+                e.getCause().printStackTrace();
+                ctx.getChannel().close();
+                sw = (EnhancedSwitchHandler)channelIDToSwitchMap.get(e.getChannel().getId());
+                sw.stop();
+            }
+
+            statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.EXCEPTION_CAUGHT);
+        }
+
+        @Override
+        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
+                throws Exception {
+            Integer messageChannelId = e.getChannel().getId();
+            IEnhancedSwitch swHan = (EnhancedSwitchHandler)channelIDToSwitchMap.get(messageChannelId);
+
+            if (e.getMessage() instanceof List) {
+                //@SuppressWarnings("unchecked")
+                List<OFMessage> msglist = (List<OFMessage>)e.getMessage();
+                if (msglist != null){ // this check actually brought down rate to some extent - weird !!!
+                    for (OFMessage ofm : msglist) {
+                        try {
+
+                            // Do the actual packet processing
+                            processOFMessage(ofm, messageChannelId);
+                        }
+                        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);
+                        }
+                    }
+                }
+            }
+
+            // Flush all flow-mods/packet-out/stats generated from this "train"
+            swHan.flushBufferedMessages();
+
+            statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.MESSAGE_RECEIVED);
+
+
+        }
+
+
+        public void processOFMessage(OFMessage ofm, Integer channelID){
+            IEnhancedSwitch switchHandler = (IEnhancedSwitch) channelIDToSwitchMap.get(channelID);
+            statsHandler.countForEntitySimpleMeasurement(channelID, TrafficStatisticsHandler.ENTITY_COUNTER_RCV_MSG);
+            if (switchHandler != null){
+                switchHandler.handleMessage(ofm);
+            }
+        }
+
+
+    }
+
+
+    protected class ControllerServerBootstrap{
+
+        private int workerThreads = 0;
+        private EnhancedController controller = null;
+
+        public ControllerServerBootstrap(EnhancedController controller){
+            this.controller = controller;
+        }
+
+
+        public void startServer(int numWorkerThreads, String openFlowHost, int openFlowPort, OFChannelHandler ofchan){
+            this.workerThreads = numWorkerThreads;
+            try {
+                final ServerBootstrap bootstrap = createServerBootStrap();
+
+                 bootstrap.setOption("reuseAddr", true);
+                 bootstrap.setOption("child.keepAlive", true);
+                 bootstrap.setOption("child.tcpNoDelay", true);
+                 bootstrap.setOption("child.receiveBufferSize", EnhancedController.RECEIVE_BUFFER_SIZE);
+                 bootstrap.setOption("child.sendBufferSize", EnhancedController.SEND_BUFFER_SIZE);
+
+                 // better to have an receive buffer predictor
+                 //bootstrap.setOption("receiveBufferSizePredictorFactory",
+                 //      new AdaptiveReceiveBufferSizePredictorFactory());
+                 //if the server is sending 1000 messages per sec, optimum write buffer water marks will
+                 //prevent unnecessary throttling, Check NioSocketChannelConfig doc
+                 //bootstrap.setOption("writeBufferLowWaterMark", WRITE_BUFFER_LOW_WATERMARK);
+                 //bootstrap.setOption("writeBufferHighWaterMark", WRITE_BUFFER_HIGH_WATERMARK);
+
+                 // TODO: IMPORTANT: If the threadpool is supplied as null, ExecutionHandler would
+                 // not be present in pipeline. If the load increases and ordering is required ,
+                 // use OrderedMemoryAwareThreadPoolExecutor as argument instead of null
+
+                 /*
+                 execHandler = new OrderedMemoryAwareThreadPoolExecutor(
+                                 OMATPE_CORE_POOL_SIZE,
+                                 OMATPE_PER_CHANNEL_SIZE,
+                                 OMATPE_POOL_WIDE_SIZE,
+                                 OMATPE_THREAD_KEEP_ALIVE_IN_MILLISECONDS,
+                                 TimeUnit.MILLISECONDS,
+                                 new ObjectSizeEstimator() {
+
+                                    @Override
+                                    public int estimateSize(Object o) {
+                                        return 30000;
+                                    }
+                                },
+                                Executors.defaultThreadFactory());     */
+
+                 execHandler = new OrderedMemoryAwareThreadPoolExecutor(
+                         OMATPE_CORE_POOL_SIZE,
+                         OMATPE_PER_CHANNEL_SIZE,
+                         OMATPE_POOL_WIDE_SIZE,
+                         OMATPE_THREAD_KEEP_ALIVE_IN_MILLISECONDS,
+                         TimeUnit.MILLISECONDS);
+
+
+
+                 ChannelPipelineFactory pfact =
+                         new OpenflowPipelineFactory(controller, execHandler);
+                 bootstrap.setPipelineFactory(pfact);
+                 InetSocketAddress sa =
+                         (openFlowHost == null)
+                         ? new InetSocketAddress(openFlowPort)
+                         : new InetSocketAddress(openFlowHost, openFlowPort);
+                 final ChannelGroup cg = new DefaultChannelGroup();
+                 cg.add(bootstrap.bind(sa));
+
+
+             } catch (Exception e) {
+                 throw new RuntimeException(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));
+            }
+        }
+
+
+
+    }
+
+
+    /**
+     * Method called by SwitchHandler once the handshake state is completed
+     *
+     * @param sw
+     */
+    public void switchAdded(SwitchEvent switchEv, Integer switchChannelID){
+
+        ISwitch sw = switchEv.getSwitch();
+        Long switchId = sw.getId();
+
+        connectedSwitches.put(switchId, sw);
+        statsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.CONNECTED_SWITCHES);
+
+        logger.info("Switch with DPID : {} connected ", switchId);
+
+        notifySwitchAdded(sw);
+    }
+
+
+    /**
+     * Method called by SwitchHandler switch is disconnected
+     *
+     * @param sw
+     */
+
+    public void switchDeleted(SwitchEvent switchEv, Integer switchChannelID){
+        ISwitch sw = switchEv.getSwitch();
+        disconnectSwitch(sw, switchChannelID);
+    }
+
+
+    /**
+     * Method called by SwitchHandler when it encounters any errors
+     *
+     *
+     * @param sw
+     */
+
+    public void switchError(SwitchEvent switchEv, Integer switchChannelID){
+
+    }
+
+
+    public void switchMessage(SwitchEvent switchEv, Integer switchChannelID){
+        long startTime = 0L;
+        long endTime = 0L;
+
+
+        OFMessage msg = switchEv.getMsg();
+        ISwitch sw = switchEv.getSwitch();
+        if (msg != null) {
+            //try{
+            //    lock.lock();
+                IMessageListener listener = messageListeners
+                        .get(msg.getType());
+                if (listener != null) {
+                    //logger.debug("delegating to msg-receiver");
+                    //startTime = System.nanoTime();
+                    listener.receive(sw, msg);
+                    //endTime = System.nanoTime();
+                    //this.statsHandler.reportPacketInProcessingTime(endTime - startTime);
+                }
+            //}
+            //finally{
+            //    lock.unlock();
+            //}
+        }
+    }
+
+    public void disconnectSwitch(ISwitch sw, Integer switchChannelID){
+        Long sid = null;
+        if (((EnhancedSwitchHandler) sw).isOperational()) {
+            sid = sw.getId();
+
+            this.connectedSwitches.remove(sid);
+            this.channelIDToSwitchMap.remove(switchChannelID);
+            notifySwitchDeleted(sw);
+        }
+        //((EnhancedSwitchHandler) sw).stop();
+        logger.info("Switch with DPID {} disconnected", sid);
+        sw = null;
+    }
+
+
+    private void notifySwitchAdded(ISwitch sw) {
+        if (switchStateListener != null) {
+            switchStateListener.switchAdded(sw);
+        }
+    }
+
+    private void notifySwitchDeleted(ISwitch sw) {
+        if (switchStateListener != null) {
+            switchStateListener.switchDeleted(sw);
+        }
+    }
+
+    @Override
+    public Status disconnect(Node node) {
+        ISwitch sw = getSwitch((Long)node.getID());
+        if (sw != null) {
+            if (sw instanceof EnhancedSwitchHandler) {
+                EnhancedSwitchHandler eSw = (EnhancedSwitchHandler)sw;
+                disconnectSwitch(sw, eSw.getSwitchChannelID());
+            }
+        }
+        return new Status(StatusCode.SUCCESS);
+    }
+
+    @Override
+    public Node connect(String connectionIdentifier, Map<ConnectionConstants, String> params) {
+        return null;
+    }
+
+    /**
+     * View Change notification
+     */
+    public void notifyClusterViewChanged() {
+        for (ISwitch sw : connectedSwitches.values()) {
+            notifySwitchAdded(sw);
+        }
+    }
+
+    /**
+     * Node Disconnected from the node's master controller.
+     */
+    @Override
+    public void notifyNodeDisconnectFromMaster(Node node) {
+        ISwitch sw = connectedSwitches.get((Long)node.getID());
+        if (sw != null) notifySwitchAdded(sw);
+    }
+}
diff --git a/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/EnhancedSwitchHandler.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/EnhancedSwitchHandler.java
new file mode 100644 (file)
index 0000000..91a2806
--- /dev/null
@@ -0,0 +1,823 @@
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedSelectorException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.TimerTask;
+import org.opendaylight.controller.protocol_plugin.openflow.core.IEnhancedSwitch;
+import org.opendaylight.controller.protocol_plugin.openflow.core.ISwitch;
+import org.opendaylight.controller.protocol_plugin.openflow.core.internal.SwitchEvent.SwitchEventType;
+import org.openflow.protocol.OFBarrierReply;
+import org.openflow.protocol.OFBarrierRequest;
+import org.openflow.protocol.OFEchoReply;
+import org.openflow.protocol.OFError;
+import org.openflow.protocol.OFFeaturesReply;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFGetConfigReply;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFPortStatus;
+import org.openflow.protocol.OFSetConfig;
+import org.openflow.protocol.OFStatisticsReply;
+import org.openflow.protocol.OFStatisticsRequest;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
+import org.openflow.protocol.OFPhysicalPort.OFPortFeatures;
+import org.openflow.protocol.OFPhysicalPort.OFPortState;
+import org.openflow.protocol.OFPortStatus.OFPortReason;
+import org.openflow.protocol.factory.BasicFactory;
+import org.openflow.protocol.factory.MessageParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EnhancedSwitchHandler implements IEnhancedSwitch {
+
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(EnhancedSwitchHandler.class);
+    private static final int switchLivenessTimeout = getSwitchLivenessTimeout();
+    private int MESSAGE_RESPONSE_TIMER = 2000;
+
+    private EnhancedController controller = null;
+    private Integer switchChannelID = null;
+    private Channel channel;
+    private long lastMsgReceivedTimeStamp = 0;
+    private SwitchState state = null;
+    private BasicFactory factory = null;
+    private HashedWheelTimer timer = null;
+    private SwitchLivelinessTimerTask switchLivelinessTask = null;
+    private Timeout switchLivelinessTaskHandle = null;
+    private long sid;
+    private AtomicInteger xid;
+    private int buffers;
+    private int capabilities;
+    private byte tables;
+    private int actions;
+    private Map<Short, OFPhysicalPort> physicalPorts;
+    private Map<Short, Integer> portBandwidth;
+    private Date connectedDate;
+    private ExecutorService executor = null;
+    private ConcurrentHashMap<Integer, Callable<Object>> messageWaitingDone;
+    private Integer responseTimerValue;
+    private TrafficStatisticsHandler trafficStatsHandler = null;
+    private static final boolean START_LIVELINESS_TIMER = false;
+
+    private static final int BATCH_COUNT_FOR_FLUSHING = 3;
+    private int flushBatchTrack = 0;
+
+    /*
+    private List<OFMessage> msgBuffer = new ArrayList<OFMessage>();
+    private int bufferTrack = 0;
+    private static final int BATCH_BUFFER_THRESHOLD = 100;
+    */
+
+
+    // PLEASE .. IF THERE IS SOMETHING CALLED GOD, HELP ME GET THE THROUGHPUT WITH THIS !!
+    private List<OFMessage> flushableMsgBuffer = new ArrayList<OFMessage>();
+
+
+    public enum SwitchState {
+        NON_OPERATIONAL(0),
+        WAIT_FEATURES_REPLY(1),
+        WAIT_CONFIG_REPLY(2),
+        OPERATIONAL(3);
+
+        private int value;
+
+        private SwitchState(int value) {
+            this.value = value;
+        }
+
+        @SuppressWarnings("unused")
+        public int value() {
+            return this.value;
+        }
+    }
+
+
+    public EnhancedSwitchHandler(EnhancedController controller,
+            Integer switchConnectionChannelID,
+            Channel channel,
+            HashedWheelTimer timer,
+            ExecutorService executor,
+            TrafficStatisticsHandler tHandler){
+
+        this.controller = controller;
+        this.physicalPorts = new HashMap<Short, OFPhysicalPort>();
+        this.portBandwidth = new HashMap<Short, Integer>();
+        this.switchChannelID = switchConnectionChannelID;
+        this.timer = timer;
+        this.sid = (long) 0;
+        this.tables = (byte) 0;
+        this.actions = (int) 0;
+        this.capabilities = (int) 0;
+        this.buffers = (int) 0;
+        this.connectedDate = new Date();
+        this.state = SwitchState.NON_OPERATIONAL;
+        this.executor = executor;
+        this.messageWaitingDone = new ConcurrentHashMap<Integer, Callable<Object>>();
+        this.responseTimerValue = MESSAGE_RESPONSE_TIMER;
+        this.channel = channel;
+        this.xid = new AtomicInteger(this.channel.hashCode());
+        this.trafficStatsHandler = tHandler;
+
+    }
+
+    Integer getSwitchChannelID() {
+        return this.switchChannelID;
+    }
+
+    public void startHandler(){
+        this.factory = new BasicFactory();
+        start();
+
+    }
+
+
+    public void shutDownHandler(){
+        stop();
+
+    }
+
+
+    public void handleChannelIdle(){
+        // TODO: this is already handled by OFChannelHandler
+        // so DON'T care
+
+
+    }
+
+
+    public void start() {
+        sendFirstHello();
+    }
+
+    public void stop() {
+        cancelSwitchTimer();
+        SwitchEvent ev = new SwitchEvent(SwitchEventType.SWITCH_DELETE, this, null);
+        controller.switchDeleted(ev, switchChannelID);
+    }
+
+    private void cancelSwitchTimer() {
+        if (switchLivelinessTaskHandle != null){
+            this.switchLivelinessTaskHandle.cancel();
+        }
+    }
+
+
+    public void handleCaughtException(){
+
+
+
+    }
+
+
+
+
+    @Override
+    public int getNextXid() {
+        return this.xid.incrementAndGet();
+    }
+
+    @Override
+    public Long getId() {
+        return this.sid;
+    }
+
+    @Override
+    public Byte getTables() {
+        return this.tables;
+    }
+
+    @Override
+    public Integer getActions() {
+        return this.actions;
+    }
+
+    @Override
+    public Integer getCapabilities() {
+        return this.capabilities;
+    }
+
+    @Override
+    public Integer getBuffers() {
+        return this.buffers;
+    }
+
+    @Override
+    public Date getConnectedDate() {
+        return this.connectedDate;
+    }
+
+    @Override
+    public Integer asyncSend(OFMessage msg) {
+        return asyncSend(msg, getNextXid());
+    }
+
+
+    @Override
+    public Integer asyncSend(OFMessage msg, int xid) {
+        // TODO:
+        // BATCHING IMPLEMENTATION. Please think hard before enablng this !!
+        // Some messages could be latency-sensitive and some could be batched
+        // for better throughput. So, below decision may not bring better
+        // throughput for latency-sensitive cases like FLOW-MODs or
+        // PACKET-OUTs
+
+        /*
+        if (bufferTrack == BUFFER_THRESHOLD){
+            this.channel.write(msgBuffer);
+            msgBuffer.clear();
+            bufferTrack = 0;
+
+        }
+        msg.setXid(xid);
+        msgBuffer.add(msg);
+        bufferTrack++;
+        */
+
+
+
+        //List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+        msg.setXid(xid);
+        synchronized( flushableMsgBuffer ) {
+            flushableMsgBuffer.add(msg);
+        }
+
+        trafficStatsHandler.countForEntitySimpleMeasurement(switchChannelID,
+                TrafficStatisticsHandler.ENTITY_COUNTER_SND_MSG);
+
+        //this.channel.write(msglist);
+
+        /*
+        if (msg.getType() == OFType.FLOW_MOD){
+            this.trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.FLOW_MOD_SENT);
+            this.trafficStatsHandler.countForRateMeasurement(TrafficStatisticsHandler.FLOW_MOD_SENT);
+        }
+        */
+
+
+        return xid;
+    }
+
+
+    @Override
+    public Integer asyncFastSend(OFMessage msg) {
+        return asyncFastSend(msg, getNextXid());
+    }
+
+    @Override
+    public Integer asyncFastSend(OFMessage msg, int xid) {
+        msg.setXid(xid);
+        List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+        msglist.add(msg);
+        this.channel.write(msglist);
+        trafficStatsHandler.countForEntitySimpleMeasurement(switchChannelID,
+                TrafficStatisticsHandler.ENTITY_COUNTER_SND_MSG);
+        return xid;
+    }
+
+    @Override
+    public Object syncSend(OFMessage msg) {
+        int xid = getNextXid();
+        return syncSend(msg, xid);
+    }
+
+    private Object syncSend(OFMessage msg, int xid) {
+        return syncMessageInternal(msg, xid, true);
+    }
+
+    @Override
+    public Map<Short, OFPhysicalPort> getPhysicalPorts() {
+        return this.physicalPorts;
+    }
+
+    @Override
+    public Set<Short> getPorts() {
+        return this.physicalPorts.keySet();
+    }
+
+    @Override
+    public OFPhysicalPort getPhysicalPort(Short portNumber) {
+        return this.physicalPorts.get(portNumber);
+    }
+
+    @Override
+    public Integer getPortBandwidth(Short portNumber) {
+        return this.portBandwidth.get(portNumber);
+    }
+
+    @Override
+    public boolean isPortEnabled(short portNumber) {
+        return isPortEnabled(physicalPorts.get(portNumber));
+    }
+
+    @Override
+    public boolean isPortEnabled(OFPhysicalPort port) {
+        if (port == null) {
+            return false;
+        }
+        int portConfig = port.getConfig();
+        int portState = port.getState();
+        if ((portConfig & OFPortConfig.OFPPC_PORT_DOWN.getValue()) > 0) {
+            return false;
+        }
+        if ((portState & OFPortState.OFPPS_LINK_DOWN.getValue()) > 0) {
+            return false;
+        }
+        if ((portState & OFPortState.OFPPS_STP_MASK.getValue()) == OFPortState.OFPPS_STP_BLOCK
+                .getValue()) {
+            return false;
+        }
+        return true;
+
+    }
+
+    @Override
+    public List<OFPhysicalPort> getEnabledPorts() {
+        List<OFPhysicalPort> result = new ArrayList<OFPhysicalPort>();
+        synchronized (this.physicalPorts) {
+            for (OFPhysicalPort port : physicalPorts.values()) {
+                if (isPortEnabled(port)) {
+                    result.add(port);
+                }
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * WARNING: CALLER WOULD BE BLOCKED
+     *
+     */
+    @Override
+    public Object getStatistics(OFStatisticsRequest req) {
+        int xid = getNextXid();
+        StatisticsCollector worker = new StatisticsCollector(this, xid, req);
+        messageWaitingDone.put(xid, worker);
+        Future<Object> submit = executor.submit(worker);
+        Object result = null;
+        try {
+            result = submit.get(responseTimerValue, TimeUnit.MILLISECONDS);
+            return result;
+        } catch (Exception e) {
+            logger.warn("Timeout while waiting for {} replies", req.getType());
+            result = null; // to indicate timeout has occurred
+            return result;
+        }
+    }
+
+    @Override
+    public boolean isOperational() {
+        return ((this.state == SwitchState.WAIT_CONFIG_REPLY) || (this.state == SwitchState.OPERATIONAL));
+    }
+
+    @Override
+    public Object syncSendBarrierMessage() {
+        OFBarrierRequest barrierMsg = new OFBarrierRequest();
+        return syncSend(barrierMsg);
+    }
+
+    @Override
+    public Object asyncSendBarrierMessage() {
+        List<OFMessage> msglist = new ArrayList<OFMessage>(1);
+        OFBarrierRequest barrierMsg = new OFBarrierRequest();
+        int xid = getNextXid();
+
+        barrierMsg.setXid(xid);
+        msglist.add(barrierMsg);
+
+        this.channel.write(msglist);
+        trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.BARRIER_REQUEST_SENT);
+        return Boolean.TRUE;
+    }
+
+
+    @Override
+    public void handleMessage(OFMessage ofMessage) {
+
+
+        logger.debug("Message received: {}", ofMessage.toString());
+        this.lastMsgReceivedTimeStamp = System.currentTimeMillis();
+        OFType type = ofMessage.getType();
+        switch (type) {
+        case HELLO:
+            logger.debug("<<<< HELLO");
+            // send feature request
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.HELLO_RECEIVED);
+            OFMessage featureRequest = factory
+                    .getMessage(OFType.FEATURES_REQUEST);
+            asyncFastSend(featureRequest);
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.FEATURES_REQUEST_SENT);
+            // delete all pre-existing flows
+            OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL);
+            OFFlowMod flowMod = (OFFlowMod) factory
+                    .getMessage(OFType.FLOW_MOD);
+            flowMod.setMatch(match).setCommand(OFFlowMod.OFPFC_DELETE)
+                    .setOutPort(OFPort.OFPP_NONE)
+                    .setLength((short) OFFlowMod.MINIMUM_LENGTH);
+            asyncFastSend(flowMod);
+            this.state = SwitchState.WAIT_FEATURES_REPLY;
+            if (START_LIVELINESS_TIMER){
+                startSwitchTimer();
+            }
+            break;
+        case ECHO_REQUEST:
+            logger.debug("<<<< ECHO REQUEST");
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ECHO_REQUEST_RECEIVED);
+            OFEchoReply echoReply = (OFEchoReply) factory
+                    .getMessage(OFType.ECHO_REPLY);
+            asyncFastSend(echoReply);
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ECHO_REPLY_SENT);
+
+            break;
+        case ECHO_REPLY:
+            logger.debug("<<<< ECHO REPLY");
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ECHO_REPLY_RECEIVED);
+            //this.probeSent = false;
+            break;
+        case FEATURES_REPLY:
+            logger.debug("<<<< FEATURES REPLY");
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.FEATURES_REPLY_RECEIVED);
+            processFeaturesReply((OFFeaturesReply) ofMessage);
+            break;
+        case GET_CONFIG_REPLY:
+            logger.debug("<<<< CONFIG REPLY");
+            // make sure that the switch can send the whole packet to the
+            // controller
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.CONFIG_REPLY_RECEIVED);
+            if (((OFGetConfigReply) ofMessage).getMissSendLength() == (short) 0xffff) {
+                this.state = SwitchState.OPERATIONAL;
+            }
+            break;
+        case BARRIER_REPLY:
+            logger.debug("<<<< BARRIER REPLY");
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.BARRIER_REPLY_RECEIVED);
+            processBarrierReply((OFBarrierReply) ofMessage);
+            break;
+        case ERROR:
+            logger.debug("<<<< ERROR");
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.ERROR_MSG_RECEIVED);
+            processErrorReply((OFError) ofMessage);
+            break;
+        case PORT_STATUS:
+            logger.debug("<<<< PORT STATUS");
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.PORT_STATUS_RECEIVED);
+            processPortStatusMsg((OFPortStatus) ofMessage);
+            break;
+        case STATS_REPLY:
+            logger.debug("<<<< STATS REPLY");
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.STATS_RESPONSE_RECEIVED);
+            processStatsReply((OFStatisticsReply) ofMessage);
+            break;
+        case PACKET_IN:
+            logger.debug("<<<< PACKET_IN");
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.PACKET_IN_RECEIVED);
+            trafficStatsHandler.countForRateMeasurement(TrafficStatisticsHandler.PACKET_IN_RECEIVED);
+            break;
+        default:
+            break;
+        } // end of switch
+        if (isOperational()) {
+            logger.debug("SWITCH IS OPERATIONAL ... forwarding");
+            SwitchEvent ev = new SwitchEvent(
+                    SwitchEvent.SwitchEventType.SWITCH_MESSAGE, this, ofMessage);
+            controller.switchMessage(ev, switchChannelID);
+        }
+    }
+
+
+    private void startSwitchTimer(){
+        if (this.timer != null){
+            if (switchLivelinessTask == null){
+                switchLivelinessTask = new SwitchLivelinessTimerTask();
+            }
+            switchLivelinessTaskHandle = timer.newTimeout(switchLivelinessTask,
+                    switchLivenessTimeout, TimeUnit.SECONDS);
+        }
+    }
+
+
+
+    /**
+     * This method returns the switch liveness timeout value. If controller did
+     * not receive any message from the switch for such a long period,
+     * controller will tear down the connection to the switch.
+     *
+     * @return The timeout value
+     */
+    private static int getSwitchLivenessTimeout() {
+        String timeout = System.getProperty("of.switchLivenessTimeout");
+        int rv = 60500;
+        try {
+            if (timeout != null) {
+                rv = Integer.parseInt(timeout);
+            }
+        } catch (Exception e) {
+        }
+        return rv;
+    }
+
+
+    private void processFeaturesReply(OFFeaturesReply reply) {
+        if (this.state == SwitchState.WAIT_FEATURES_REPLY) {
+            this.sid = reply.getDatapathId();
+            this.buffers = reply.getBuffers();
+            this.capabilities = reply.getCapabilities();
+            this.tables = reply.getTables();
+            this.actions = reply.getActions();
+            // notify core of this error event
+            for (OFPhysicalPort port : reply.getPorts()) {
+                updatePhysicalPort(port);
+            }
+            // config the switch to send full data packet
+            OFSetConfig config = (OFSetConfig) factory
+                    .getMessage(OFType.SET_CONFIG);
+            config.setMissSendLength((short) 0xffff).setLengthU(
+                    OFSetConfig.MINIMUM_LENGTH);
+            asyncFastSend(config);
+            // send config request to make sure the switch can handle the set
+            // config
+            OFMessage getConfig = factory.getMessage(OFType.GET_CONFIG_REQUEST);
+            asyncFastSend(getConfig);
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.CONFIG_REQUEST_SENT);
+            this.state = SwitchState.WAIT_CONFIG_REPLY;
+            // inform core that a new switch is now operational
+            reportSwitchStateChange(true);
+        }
+    }
+
+
+    private void updatePhysicalPort(OFPhysicalPort port) {
+        Short portNumber = port.getPortNumber();
+        physicalPorts.put(portNumber, port);
+        portBandwidth
+                .put(portNumber,
+                        port.getCurrentFeatures()
+                                & (OFPortFeatures.OFPPF_10MB_FD.getValue()
+                                        | OFPortFeatures.OFPPF_10MB_HD
+                                                .getValue()
+                                        | OFPortFeatures.OFPPF_100MB_FD
+                                                .getValue()
+                                        | OFPortFeatures.OFPPF_100MB_HD
+                                                .getValue()
+                                        | OFPortFeatures.OFPPF_1GB_FD
+                                                .getValue()
+                                        | OFPortFeatures.OFPPF_1GB_HD
+                                                .getValue() | OFPortFeatures.OFPPF_10GB_FD
+                                            .getValue()));
+        trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.UPDATE_PHYSICAL_PORT);
+    }
+
+
+    private void reportSwitchStateChange(boolean added) {
+        SwitchEvent ev = null;
+        if (added) {
+            ev = new SwitchEvent(SwitchEvent.SwitchEventType.SWITCH_ADD, this, null);
+            controller.switchAdded(ev, switchChannelID);
+        } else {
+            ev = new SwitchEvent(SwitchEvent.SwitchEventType.SWITCH_DELETE, this, null);
+            controller.switchDeleted(ev, switchChannelID);
+        }
+    }
+
+
+    protected class SwitchLivelinessTimerTask implements TimerTask {
+
+        @Override
+        public void run(Timeout timeout) throws Exception {
+
+            // set this reference in parent so that cancellation is
+            // possible
+            switchLivelinessTaskHandle = timeout;
+            Long now = System.currentTimeMillis();
+            if ((now - lastMsgReceivedTimeStamp) > switchLivenessTimeout) {
+                if (state == SwitchState.WAIT_FEATURES_REPLY) {
+                    // send another features request
+                    OFMessage request = factory
+                            .getMessage(OFType.FEATURES_REQUEST);
+                    asyncFastSend(request);
+                } else {
+                    if (state == SwitchState.WAIT_CONFIG_REPLY) {
+                        // send another config request
+                        OFSetConfig config = (OFSetConfig) factory
+                                .getMessage(OFType.SET_CONFIG);
+                        config.setMissSendLength((short) 0xffff)
+                        .setLengthU(OFSetConfig.MINIMUM_LENGTH);
+                        asyncFastSend(config);
+                        OFMessage getConfig = factory
+                                .getMessage(OFType.GET_CONFIG_REQUEST);
+                        asyncFastSend(getConfig);
+                    }
+                }
+            }
+            timer.newTimeout(this, switchLivenessTimeout, TimeUnit.SECONDS);
+
+        }
+    }
+
+
+    /*
+     * Either a BarrierReply or a OFError is received. If this is a reply for an
+     * outstanding sync message, wake up associated task so that it can continue
+     */
+    private void processBarrierReply(OFBarrierReply msg) {
+        Integer xid = msg.getXid();
+        SynchronousMessage worker = (SynchronousMessage) messageWaitingDone
+                .remove(xid);
+        if (worker == null) {
+            return;
+        }
+        worker.wakeup();
+    }
+
+    private void processErrorReply(OFError errorMsg) {
+        try{
+            OFMessage offendingMsg = errorMsg.getOffendingMsg();
+            Integer xi = 0;
+            if (offendingMsg != null) {
+                xi = offendingMsg.getXid();
+            } else {
+                xi = errorMsg.getXid();
+            }
+        }
+        catch(MessageParseException mpe){
+            reportError(mpe);
+        }
+    }
+
+    private void processPortStatusMsg(OFPortStatus msg) {
+        OFPhysicalPort port = msg.getDesc();
+        if (msg.getReason() == (byte) OFPortReason.OFPPR_MODIFY.ordinal()) {
+            updatePhysicalPort(port);
+        } else if (msg.getReason() == (byte) OFPortReason.OFPPR_ADD.ordinal()) {
+            updatePhysicalPort(port);
+        } else if (msg.getReason() == (byte) OFPortReason.OFPPR_DELETE
+                .ordinal()) {
+            deletePhysicalPort(port);
+        }
+
+    }
+
+    private void deletePhysicalPort(OFPhysicalPort port) {
+        Short portNumber = port.getPortNumber();
+        physicalPorts.remove(portNumber);
+        portBandwidth.remove(portNumber);
+    }
+
+    private void processStatsReply(OFStatisticsReply reply) {
+        Integer xid = reply.getXid();
+        StatisticsCollector worker = (StatisticsCollector) messageWaitingDone
+                .get(xid);
+        if (worker == null) {
+            return;
+        }
+        if (worker.collect(reply)) {
+            // if all the stats records are received (collect() returns true)
+            // then we are done.
+            messageWaitingDone.remove(xid);
+            worker.wakeup();
+        }
+    }
+
+
+    /**
+     * This method performs synchronous operations for a given message. If
+     * syncRequest is set to true, the message will be sent out followed by a
+     * Barrier request message. Then it's blocked until the Barrier rely arrives
+     * or timeout. If syncRequest is false, it simply skips the message send and
+     * just waits for the response back.
+     *
+     * @param msg
+     *            Message to be sent
+     * @param xid
+     *            Message XID
+     * @param request
+     *            If set to true, the message the message will be sent out
+     *            followed by a Barrier request message. If set to false, it
+     *            simply skips the sending and just waits for the Barrier reply.
+     * @return the result
+     */
+    private Object syncMessageInternal(OFMessage msg, int xid, boolean syncRequest) {
+        Object result = null;
+
+        SynchronousMessage worker = new SynchronousMessage(this, xid, msg, syncRequest);
+        messageWaitingDone.put(xid, worker);
+
+        Boolean status = false;
+        Future<Object> submit = executor.submit(worker);
+        try {
+            result = submit.get(responseTimerValue, TimeUnit.MILLISECONDS);
+            messageWaitingDone.remove(xid);
+            if (result == null) {
+                // if result is null, then it means the switch can handle this
+                // message successfully
+                // convert the result into a Boolean with value true
+                status = true;
+                // logger.debug("Successfully send " +
+                // msg.getType().toString());
+                result = status;
+            } else {
+                // if result is not null, this means the switch can't handle
+                // this message
+                // the result if OFError already
+                logger.debug("Send {} failed --> {}", msg.getType().toString(),
+                        ((OFError) result).toString());
+            }
+            return result;
+        } catch (Exception e) {
+            logger.warn("Timeout while waiting for {} reply", msg.getType()
+                    .toString());
+            // convert the result into a Boolean with value false
+            status = false;
+            result = status;
+            return result;
+        }
+
+
+    }
+
+
+    private void sendFirstHello() {
+        try {
+            OFMessage msg = factory.getMessage(OFType.HELLO);
+            asyncFastSend(msg);
+            trafficStatsHandler.countForSimpleMeasurement(TrafficStatisticsHandler.HELLO_SENT);
+            trafficStatsHandler.addEntityForCounter(switchChannelID, TrafficStatisticsHandler.ENTITY_COUNTER_RCV_MSG);
+            trafficStatsHandler.addEntityForCounter(switchChannelID, TrafficStatisticsHandler.ENTITY_COUNTER_SND_MSG);
+        } catch (Exception e) {
+            reportError(e);
+        }
+    }
+
+
+    private void reportError(Exception e) {
+        if (e instanceof AsynchronousCloseException
+                || e instanceof InterruptedException
+                || e instanceof SocketException || e instanceof IOException
+                || e instanceof ClosedSelectorException) {
+            logger.error("Caught exception {}", e.getMessage());
+        } else {
+            logger.error("Caught exception ", e);
+        }
+        // notify core of this error event and disconnect the switch
+
+        // TODO: We do not need this because except-hanling is done by
+        // Controller's OFChannelHandler
+
+        /*
+        SwitchEvent ev = new SwitchEvent(
+                SwitchEvent.SwitchEventType.SWITCH_ERROR, this, null);
+
+        controller.switchError(ev, switchChannelID);
+        */
+    }
+
+
+    @Override
+    public void flushBufferedMessages() {
+        //flushBatchTrack++;
+        //if (flushBatchTrack > BATCH_COUNT_FOR_FLUSHING){
+        synchronized (flushableMsgBuffer) {
+            if (flushableMsgBuffer.size() > 0){
+                channel.write(flushableMsgBuffer);
+                flushableMsgBuffer.clear();
+            }
+        }
+        //    flushBatchTrack = 0;
+        //}
+
+    }
+
+    @Override
+    public SocketAddress getRemoteAddress() {
+        return (channel != null) ? channel.getRemoteAddress() : null;
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() {
+        return (channel != null) ? channel.getLocalAddress() : null;
+    }
+
+}
diff --git a/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFChannelState.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFChannelState.java
new file mode 100644 (file)
index 0000000..b66ce97
--- /dev/null
@@ -0,0 +1,51 @@
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openflow.protocol.OFFeaturesReply;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.statistics.OFDescriptionStatistics;
+
+/**
+ * Wrapper class to hold state for the OpenFlow switch connection
+ * @author readams
+ */
+class OFChannelState {
+
+    /**
+     * State for handling the switch handshake
+     */
+    protected enum HandshakeState {
+        /**
+         * Beginning state
+         */
+        START,
+
+        /**
+         * Received HELLO from switch
+         */
+        HELLO,
+
+        /**
+         * We've received the features reply
+         * Waiting for Config and Description reply
+         */
+        FEATURES_REPLY,
+
+        /**
+         * Switch is ready for processing messages
+         */
+        READY
+
+    }
+
+    protected volatile HandshakeState hsState = HandshakeState.START;
+    protected boolean hasGetConfigReply = false;
+    protected boolean hasDescription = false;
+    protected boolean switchBindingDone = false;
+
+    protected OFFeaturesReply featuresReply = null;
+    protected OFDescriptionStatistics description = null;
+    protected List<OFMessage> queuedOFMessages = new ArrayList<OFMessage>();
+}
\ No newline at end of file
diff --git a/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFMessageDecoder.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFMessageDecoder.java
new file mode 100644 (file)
index 0000000..46472e6
--- /dev/null
@@ -0,0 +1,43 @@
+package org.opendaylight.controller.protocol_plugin.openflow.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 = new BasicFactory();
+
+    @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/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFMessageEncoder.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OFMessageEncoder.java
new file mode 100644 (file)
index 0000000..12775c6
--- /dev/null
@@ -0,0 +1,39 @@
+package org.opendaylight.controller.protocol_plugin.openflow.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/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OpenflowPipelineFactory.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/OpenflowPipelineFactory.java
new file mode 100644 (file)
index 0000000..3414632
--- /dev/null
@@ -0,0 +1,66 @@
+package org.opendaylight.controller.protocol_plugin.openflow.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.HashedWheelTimer;
+import org.jboss.netty.util.Timer;
+
+/**
+ * Creates a ChannelPipeline for a server-side openflow channel
+ * @author readams
+ */
+public class OpenflowPipelineFactory implements ChannelPipelineFactory {
+
+    private static final int READ_TIMEOUT = 30;
+    private static final int READER_IDLE_TIMEOUT = 20;
+    private static final int WRITER_IDLE_TIMEOUT = 25;
+    private static final int ALL_IDLE_TIMEOUT = 0;
+
+    protected EnhancedController controller;
+    protected ThreadPoolExecutor pipelineExecutor;
+    protected Timer timer;
+    protected IdleStateHandler idleHandler;
+    protected ReadTimeoutHandler readTimeoutHandler;
+
+    public OpenflowPipelineFactory(EnhancedController controller,
+                                   ThreadPoolExecutor pipelineExecutor) {
+        super();
+        this.controller = controller;
+        this.pipelineExecutor = pipelineExecutor;
+        this.timer = new HashedWheelTimer();
+        this.idleHandler = new IdleStateHandler(timer, READER_IDLE_TIMEOUT, WRITER_IDLE_TIMEOUT, ALL_IDLE_TIMEOUT);
+        this.readTimeoutHandler = new ReadTimeoutHandler(timer, READ_TIMEOUT);
+    }
+
+    @Override
+    public ChannelPipeline getPipeline() throws Exception {
+        //OFChannelState state = new OFChannelState();
+
+
+        ChannelPipeline pipeline = Channels.pipeline();
+
+        /*
+        if (pipelineExecutor != null)
+            pipeline.addLast("pipelineExecutor",
+                             new ExecutionHandler(pipelineExecutor));*/
+        pipeline.addLast("ofmessagedecoder", new OFMessageDecoder());
+        pipeline.addLast("ofmessageencoder", new OFMessageEncoder());
+        pipeline.addLast("idle", idleHandler);
+        //pipeline.addLast("timeout", readTimeoutHandler);
+        //pipeline.addLast("handshaketimeout",
+        //                 new HandshakeTimeoutHandler(state, timer, 15));
+
+        /*
+        if (pipelineExecutor != null)
+            pipeline.addLast("pipelineExecutor",
+                             new ExecutionHandler(pipelineExecutor));*/
+        pipeline.addLast("handler", controller.getChannelHandler());
+        return pipeline;
+    }
+}
\ No newline at end of file
diff --git a/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/TrafficStatisticsHandler.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/TrafficStatisticsHandler.java
new file mode 100644 (file)
index 0000000..540ec39
--- /dev/null
@@ -0,0 +1,336 @@
+package org.opendaylight.controller.protocol_plugin.openflow.core.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.TimerTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+public class TrafficStatisticsHandler {
+
+
+    private static final Logger logger = LoggerFactory
+            .getLogger(EnhancedController.class);
+
+    private Timeout statsTaskHandle = null;
+
+    private Map<String, AtomicLong> currentCounterMap = new ConcurrentHashMap<String, AtomicLong>();
+    private Map<String, AtomicLong> lastCounterMap = new ConcurrentHashMap<String, AtomicLong>();
+    private Map<String, Long> lastMeasurementTStamp = new ConcurrentHashMap<String, Long>();
+    private List<String> rawRateMeasurementData = new ArrayList<String>();
+
+    private ConcurrentHashMap<Integer, AtomicLong> msgRcvEntityCounter =
+            new ConcurrentHashMap<Integer, AtomicLong>();
+    private ConcurrentHashMap<Integer, AtomicLong> msgSndEntityCounter =
+            new ConcurrentHashMap<Integer, AtomicLong>();
+
+
+
+    private static final long STATISTICS_RATE_INTERVAL = 25000;
+    private static final int STATISTICS_PRINT_INTREVAL = 180;
+    private static List<Long> packetInProcessingTimeList = new ArrayList<Long>();
+    private static List<Integer> pendingTaskCountList = new ArrayList<Integer>();
+
+
+    public static final String ENTITY_COUNTER_RCV_MSG = "SWITCHWISE_RCV_MSG_COUNT";
+    public static final String ENTITY_COUNTER_SND_MSG = "SWITCHWISE_SND_MSG_COUNT";
+
+    private HashedWheelTimer hashedWheelTimer = null;
+
+    public static final String ADDED_SWITCHES = "ADDED_SWITCHES";
+    public static final String CONNECTED_SWITCHES = "CONNECTED_SWITCHES";
+    public static final String DELETED_SWITCHES = "DELETED_SWITCHES";
+    public static final String DISCONNECTED_SWITCHES = "DISCONNECTED_SWITCHES";
+    public static final String SWITCH_ERROR = "SWITCH_ERROR";
+
+
+
+    public static final String EXCEPTION_CAUGHT = "EXCEPTION_CAUGHT";
+    public static final String MESSAGE_RECEIVED = "MESSAGE_RECEIVED";  // DO RATE-MEASUREMENTS
+
+    public static final String MSG_LISTENER_INVOCATION = "MSG_LISTENER_INVOCATION";
+    public static final String HELLO_RECEIVED = "HELLO_RECEIVED";
+    public static final String HELLO_SENT = "HELLO_SENT";
+    public static final String ECHO_REQUEST_SENT = "ECHO_REQUEST_SENT";
+    public static final String ECHO_REQUEST_RECEIVED = "ECHO_REQUEST_RECEIVED";
+    public static final String ECHO_REPLY_SENT = "ECHO_REPLY_SENT";
+    public static final String ECHO_REPLY_RECEIVED = "ECHO_REPLY_RECEIVED";
+    public static final String FEATURES_REQUEST_SENT = "FEATURES_REQUEST_SENT";
+    public static final String FEATURES_REQUEST_RECEIVED = "FEATURES_REQUEST_RECEIVED";
+    public static final String FEATURES_REPLY_SENT = "FEATURES_REPLY_SENT";
+    public static final String FEATURES_REPLY_RECEIVED = "FEATURES_REPLY_RECEIVED";
+    public static final String CONFIG_REQUEST_SENT = "CONFIG_REQUEST_SENT";
+    public static final String CONFIG_REQUEST_RECEIVED = "CONFIG_REQUEST_RECEIVED";
+    public static final String CONFIG_REPLY_SENT = "CONFIG_REPLY_SENT";
+    public static final String CONFIG_REPLY_RECEIVED = "CONFIG_REPLY_RECEIVED";
+    public static final String BARRIER_REQUEST_SENT = "BARRIER_REQUEST_SENT";
+    public static final String BARRIER_REPLY_RECEIVED = "BARRIER_REPLY_RECEIVED";
+    public static final String ERROR_MSG_RECEIVED = "ERROR_MSG_RECEIVED";
+    public static final String PORT_STATUS_RECEIVED = "PORT_STATUS";
+    public static final String PACKET_IN_RECEIVED = "PACKET_IN";        // DO RATE-MEASUREMENTS
+    public static final String FLOW_MOD_SENT = "FLOW_MOD_SENT";            // DO RATE-MEASUREMENTS ==> To be determined as to where to collect this data from
+    public static final String STATS_REQUEST_SENT = "STATS_REQUEST_SENT";     // DO RATE-MEASUREMENTS ==> To be determined as to where to collect this data from
+    public static final String STATS_RESPONSE_RECEIVED = "STATS_RESPONSE_RECEIVED";
+
+    public static final String UPDATE_PHYSICAL_PORT = "UPDATE_PHYSICAL_PORT";
+
+    private static final int TASK_SCHEDULE_INITIAL_DELAY_IN_SECONDS = 10;
+
+    private int trackPktInProcessing = 0;
+    private static final int PKT_IN_PROCESSING_DURATION_SAMPLING_COUNT = 100000;
+
+
+    public TrafficStatisticsHandler(HashedWheelTimer timer){
+        this.hashedWheelTimer = timer;
+    }
+
+
+    public void init(){
+
+        currentCounterMap.put(MSG_LISTENER_INVOCATION, new AtomicLong(0));
+        currentCounterMap.put(ADDED_SWITCHES, new AtomicLong(0));
+        currentCounterMap.put(DELETED_SWITCHES, new AtomicLong(0));
+        currentCounterMap.put(CONNECTED_SWITCHES, new AtomicLong(0));
+        currentCounterMap.put(DISCONNECTED_SWITCHES, new AtomicLong(0));
+        currentCounterMap.put(SWITCH_ERROR, new AtomicLong(0));
+        currentCounterMap.put(HELLO_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(HELLO_SENT, new AtomicLong(0));
+        currentCounterMap.put(ECHO_REQUEST_SENT, new AtomicLong(0));
+        currentCounterMap.put(ECHO_REQUEST_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(ECHO_REPLY_SENT, new AtomicLong(0));
+        currentCounterMap.put(ECHO_REPLY_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(EXCEPTION_CAUGHT, new AtomicLong(0));
+        currentCounterMap.put(MESSAGE_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(FEATURES_REQUEST_SENT, new AtomicLong(0));
+        currentCounterMap.put(FEATURES_REQUEST_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(FEATURES_REPLY_SENT, new AtomicLong(0));
+        currentCounterMap.put(FEATURES_REPLY_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(CONFIG_REQUEST_SENT, new AtomicLong(0));
+        currentCounterMap.put(CONFIG_REQUEST_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(CONFIG_REPLY_SENT, new AtomicLong(0));
+        currentCounterMap.put(CONFIG_REPLY_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(BARRIER_REQUEST_SENT, new AtomicLong(0));
+        currentCounterMap.put(BARRIER_REPLY_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(ERROR_MSG_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(PORT_STATUS_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(PACKET_IN_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(FLOW_MOD_SENT, new AtomicLong(0));
+        currentCounterMap.put(STATS_REQUEST_SENT, new AtomicLong(0));
+        currentCounterMap.put(STATS_RESPONSE_RECEIVED, new AtomicLong(0));
+        currentCounterMap.put(UPDATE_PHYSICAL_PORT, new AtomicLong(0));
+
+        lastCounterMap.put(MSG_LISTENER_INVOCATION, new AtomicLong(0));
+        lastCounterMap.put(ADDED_SWITCHES, new AtomicLong(0));
+        lastCounterMap.put(DELETED_SWITCHES, new AtomicLong(0));
+        lastCounterMap.put(CONNECTED_SWITCHES, new AtomicLong(0));
+        lastCounterMap.put(DISCONNECTED_SWITCHES, new AtomicLong(0));
+        lastCounterMap.put(SWITCH_ERROR, new AtomicLong(0));
+        lastCounterMap.put(HELLO_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(HELLO_SENT, new AtomicLong(0));
+        lastCounterMap.put(FEATURES_REQUEST_SENT, new AtomicLong(0));
+        lastCounterMap.put(FEATURES_REQUEST_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(ECHO_REQUEST_SENT, new AtomicLong(0));
+        lastCounterMap.put(ECHO_REQUEST_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(ECHO_REPLY_SENT, new AtomicLong(0));
+        lastCounterMap.put(ECHO_REPLY_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(EXCEPTION_CAUGHT, new AtomicLong(0));
+        lastCounterMap.put(MESSAGE_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(FEATURES_REPLY_SENT, new AtomicLong(0));
+        lastCounterMap.put(FEATURES_REPLY_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(CONFIG_REQUEST_SENT, new AtomicLong(0));
+        lastCounterMap.put(CONFIG_REQUEST_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(CONFIG_REPLY_SENT, new AtomicLong(0));
+        lastCounterMap.put(CONFIG_REPLY_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(BARRIER_REQUEST_SENT, new AtomicLong(0));
+        lastCounterMap.put(BARRIER_REPLY_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(ERROR_MSG_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(PORT_STATUS_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(PACKET_IN_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(FLOW_MOD_SENT, new AtomicLong(0));
+        lastCounterMap.put(STATS_REQUEST_SENT, new AtomicLong(0));
+        lastCounterMap.put(STATS_RESPONSE_RECEIVED, new AtomicLong(0));
+        lastCounterMap.put(UPDATE_PHYSICAL_PORT, new AtomicLong(0));
+
+        lastMeasurementTStamp.put(MSG_LISTENER_INVOCATION, new Long(0));
+        lastMeasurementTStamp.put(ADDED_SWITCHES, new Long(0));
+        lastMeasurementTStamp.put(DELETED_SWITCHES, new Long(0));
+        lastMeasurementTStamp.put(CONNECTED_SWITCHES, new Long(0));
+        lastMeasurementTStamp.put(DISCONNECTED_SWITCHES, new Long(0));
+        lastMeasurementTStamp.put(SWITCH_ERROR, new Long(0));
+        lastMeasurementTStamp.put(HELLO_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(HELLO_SENT, new Long(0));
+        lastMeasurementTStamp.put(ECHO_REQUEST_SENT, new Long(0));
+        lastMeasurementTStamp.put(ECHO_REQUEST_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(ECHO_REPLY_SENT, new Long(0));
+        lastMeasurementTStamp.put(ECHO_REPLY_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(EXCEPTION_CAUGHT, new Long(0));
+        lastMeasurementTStamp.put(MESSAGE_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(FEATURES_REQUEST_SENT, new Long(0));
+        lastMeasurementTStamp.put(FEATURES_REQUEST_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(FEATURES_REPLY_SENT, new Long(0));
+        lastMeasurementTStamp.put(FEATURES_REPLY_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(CONFIG_REQUEST_SENT, new Long(0));
+        lastMeasurementTStamp.put(CONFIG_REQUEST_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(CONFIG_REPLY_SENT, new Long(0));
+        lastMeasurementTStamp.put(CONFIG_REPLY_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(BARRIER_REQUEST_SENT, new Long(0));
+        lastMeasurementTStamp.put(BARRIER_REPLY_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(ERROR_MSG_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(PORT_STATUS_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(PACKET_IN_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(FLOW_MOD_SENT, new Long(0));
+        lastMeasurementTStamp.put(STATS_REQUEST_SENT, new Long(0));
+        lastMeasurementTStamp.put(STATS_RESPONSE_RECEIVED, new Long(0));
+        lastMeasurementTStamp.put(UPDATE_PHYSICAL_PORT, new Long(0));
+
+        /*
+        rateMap.put(HELLO_SENT, new Double(0.00000000));
+        rateMap.put(FEATURES_REQUEST, new Double(0.00000000));
+        rateMap.put(FEATURES_REPLY, new Double(0.00000000));
+        rateMap.put(CONFIG_REQUEST, new Double(0.00000000));
+        rateMap.put(CONFIG_REPLY, new Double(0.00000000));
+        rateMap.put(PORT_STATUS, new Double(0.00000000));
+        rateMap.put(PACKET_IN, new Double(0.00000000));
+        rateMap.put(FLOW_MOD_SENT, new Double(0.00000000));
+
+
+        history.put(HELLO_SENT, new ArrayList());
+        history.put(FEATURES_REQUEST, new ArrayList());
+        history.put(FEATURES_REPLY, new ArrayList());
+        history.put(CONFIG_REQUEST, new ArrayList());
+        history.put(CONFIG_REPLY, new ArrayList());
+        history.put(PORT_STATUS, new ArrayList());
+        history.put(PACKET_IN, new ArrayList());
+        history.put(FLOW_MOD_SENT, new ArrayList());
+        */
+
+        statsTaskHandle = this.hashedWheelTimer.newTimeout(new StatsOutTask(),
+                TASK_SCHEDULE_INITIAL_DELAY_IN_SECONDS, TimeUnit.SECONDS);
+
+    }
+
+    public void stopStatsHandler(){
+        if (statsTaskHandle != null){
+            statsTaskHandle.cancel();
+        }
+    }
+
+    public void reportPacketInProcessingTime(long duration){
+        trackPktInProcessing++;
+        if (trackPktInProcessing > PKT_IN_PROCESSING_DURATION_SAMPLING_COUNT){
+            packetInProcessingTimeList.add(new Long(duration));
+            trackPktInProcessing = 0;
+        }
+    }
+
+    public void addEntityForCounter(Integer entityID, String counterType){
+        if (counterType.equalsIgnoreCase(ENTITY_COUNTER_RCV_MSG)){
+            msgRcvEntityCounter.put(entityID, new AtomicLong(0));
+        }
+        else{
+            msgSndEntityCounter.put(entityID, new AtomicLong(0));
+        }
+    }
+
+    public void countForEntitySimpleMeasurement(Integer entityID, String counterType){
+        if (counterType.equalsIgnoreCase(ENTITY_COUNTER_RCV_MSG)){
+            //msgRcvEntityCounter.get(entityID).incrementAndGet();
+        }
+        else{
+            //msgSndEntityCounter.get(entityID).incrementAndGet();
+        }
+    }
+
+
+    public void countForSimpleMeasurement(String counterName){
+        currentCounterMap.get(counterName).incrementAndGet();
+    }
+
+    public void countForRateMeasurement(String counterName){
+
+        long currCntr = currentCounterMap.get(counterName).incrementAndGet();
+        if (lastMeasurementTStamp.get(counterName) == 0){
+            lastMeasurementTStamp.put(counterName, System.currentTimeMillis());
+        }
+
+        Long currentCount = new Long(currCntr);
+        Long lastCount = lastCounterMap.get(counterName).get();
+
+        //Double rate = 0.00000000000;
+        if ((currentCount - lastCount) == STATISTICS_RATE_INTERVAL){
+            Long currentTime = System.currentTimeMillis();
+            Long lastTime = lastMeasurementTStamp.get(counterName);
+            //rate = new Double((STATISTICS_RATE_INTERVAL/(currentTime-lastTime))*1000); //convert to count/sec
+            rawRateMeasurementData.add("CN:" + counterName +
+                    ",CC:" + currentCount +
+                    ",LC:" + lastCount +
+                    ",CT:" + currentTime +
+                    ",LT:" + lastTime +
+                    ",CV:" + ((STATISTICS_RATE_INTERVAL/(currentTime-lastTime))*1000));
+            lastCounterMap.put(counterName, new AtomicLong(currentCount));
+            lastMeasurementTStamp.put(counterName, currentTime);
+            //history.get(counterName).add(String.valueOf(rate.doubleValue()));
+            //rateMap.put(counterName, rate);
+        }
+
+    }
+
+
+    private class StatsOutTask implements TimerTask {
+
+        @Override
+        public void run(Timeout timeout) throws Exception {
+
+            statsTaskHandle = timeout;
+            logger.warn(">>>>>>Raw Counter values at controller BEGIN<<<<<<<<");
+
+            for (Entry<String, AtomicLong> entry : currentCounterMap.entrySet()){
+                logger.warn("{} {}", entry.getKey(), entry.getValue());
+            }
+            logger.warn(">>>>>>Counter values at controller END  <<<<<<<<");
+
+            logger.warn(">>>>>>Entity Counter values at controller BEGIN<<<<<<<<");
+
+            for (Entry<Integer, AtomicLong> entry : msgRcvEntityCounter.entrySet()){
+                logger.warn("SwitchID {} : Rcv Msg Count {}", entry.getKey(), entry.getValue());
+            }
+            logger.warn(">>>>>>Entity Counter values at controller END  <<<<<<<<");
+
+            logger.warn(">>>>>>Raw data rate values at controller BEGIN<<<<<<<<");
+
+            for (String str : rawRateMeasurementData ){
+                logger.warn("{}", str);
+            }
+            logger.warn(">>>>>>Raw data rate values at controller END  <<<<<<<<");
+
+
+            if (packetInProcessingTimeList.size() > 0){
+                logger.warn("================ MAX PACKET_IN PROC TIME in microseconds : {}",
+                        Collections.max(packetInProcessingTimeList)/1000);
+                logger.warn("================ MIN PACKET_IN PROC TIME in microseconds : {}",
+                        Collections.min(packetInProcessingTimeList)/1000);
+                long v = 0L;
+                int track = 0;
+                for (Long val : packetInProcessingTimeList){
+                    v = v + val.longValue();
+                    track++;
+                }
+                logger.warn("================ AVG PACKET_IN PROC TIME in microseconds : {}",
+                        ((double)(v/track))/1000);
+            }
+            hashedWheelTimer.newTimeout(this, STATISTICS_PRINT_INTREVAL, TimeUnit.SECONDS);
+        }
+    }
+
+}
diff --git a/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/EnhancedActivator.java b/openflow_netty/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/EnhancedActivator.java
new file mode 100644 (file)
index 0000000..b810522
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.protocol_plugin.openflow.internal;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.protocol_plugin.openflow.core.internal.EnhancedController;
+import org.opendaylight.controller.protocol_plugin.openflow.core.internal.Controller;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Openflow protocol plugin Activator
+ *
+ *
+ */
+public class EnhancedActivator extends Activator {
+    protected static final Logger logger = LoggerFactory
+            .getLogger(EnhancedActivator.class);
+
+    // Default Constructor for the activator
+    public EnhancedActivator() {
+        super();
+        logger.debug("Enhanced activator called!");
+    }
+
+    /**
+     * Function that is used to communicate to dependency manager the list of
+     * known implementations for services that are container independent.
+     *
+     *
+     * @return An array containing all the CLASS objects that will be
+     *         instantiated in order to get an fully working implementation
+     *         Object
+     */
+    @Override
+    public Object[] getGlobalImplementations() {
+        Object[] res = super.getGlobalImplementations();
+        // Now remove the Controller.class and return the
+        // EnhancedController
+        List resList = new ArrayList(Arrays.asList(res));
+        resList.remove(Controller.class);
+        resList.add(EnhancedController.class);
+        return resList.toArray();
+    }
+
+    /**
+     * Function that is called when configuration of the dependencies is
+     * required.
+     *
+     * @param c
+     *            dependency manager Component object, used for configuring the
+     *            dependencies exported and imported
+     * @param imp
+     *            Implementation class that is being configured, needed as long
+     *            as the same routine can configure multiple implementations
+     */
+    @Override
+    public void configureGlobalInstance(Component c, Object imp) {
+        if (imp.equals(EnhancedController.class)) {
+            // Configure it like if was the Controller.class
+            super.configureGlobalInstance(c, Controller.class);
+        } else {
+            super.configureGlobalInstance(c, imp);
+        }
+    }
+}
diff --git a/third-party/commons/thirdparty/pom.xml b/third-party/commons/thirdparty/pom.xml
new file mode 100644 (file)
index 0000000..7883312
--- /dev/null
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>commons.thirdparty</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <properties>
+    <sonar.host.url>https://sonar.opendaylight.org/</sonar.host.url>
+    <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+    <sitedeploy>dav:http://nexus.opendaylight.org/content/sites/site</sitedeploy>
+    <siteplugin>3.2</siteplugin>
+    <projectinfo>2.6</projectinfo>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <compiler.version>2.3.2</compiler.version>
+    <surefire.version>2.13</surefire.version>
+  </properties>
+
+  <pluginRepositories>
+    <pluginRepository>
+      <id>central2</id>
+      <name>central2</name>
+      <url>${nexusproxy}/repositories/central2/</url>
+    </pluginRepository>
+  </pluginRepositories>
+
+  <profiles>
+    <profile>
+      <id>fastreassembly</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <version>2.4</version>
+            <executions>
+              <execution>
+                <id>copyfastreassembly</id>
+                <phase>install</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+                <configuration>
+                  <artifactItems>
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>${project.artifactId}</artifactId>
+                      <version>${project.version}</version>
+                      <destFileName>${project.groupId}.${project.artifactId}-${project.version}.jar</destFileName>
+                    </artifactItem>
+                  </artifactItems>
+                  <outputDirectory>${fastreassembly.directory}</outputDirectory>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>com.googlecode.maven-java-formatter-plugin</groupId>
+        <artifactId>maven-java-formatter-plugin</artifactId>
+        <version>0.3.1</version>
+        <configuration>
+          <excludes>
+            <exclude>**/*</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-site-plugin</artifactId>
+          <version>${siteplugin}</version>
+          <configuration>
+            <reportPlugins>
+              <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-project-info-reports-plugin</artifactId>
+                <version>${projectinfo}</version>
+                <configuration>
+                  <dependencyDetailsEnabled>false</dependencyDetailsEnabled>
+                  <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+                </configuration>
+                <reports>
+                  <report>index</report>
+                  <report>project-team</report>
+                  <report>license</report>
+                  <report>mailing-list</report>
+                  <report>plugin-management</report>
+                  <report>cim</report>
+                  <report>issue-tracking</report>
+                  <report>scm</report>
+                  <report>summary</report>
+                </reports>
+              </plugin>
+              <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <version>2.10</version>
+              </plugin>
+              <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>2.8.1</version>
+                <configuration>
+                  <doclet>org.jboss.apiviz.APIviz</doclet>
+                  <docletArtifact>
+                    <groupId>org.jboss.apiviz</groupId>
+                    <artifactId>apiviz</artifactId>
+                    <version>1.3.2.GA</version>
+                  </docletArtifact>
+                  <finalName>${project.artifactId}-${build.suffix}</finalName>
+                  <useStandardDocletOptions>true</useStandardDocletOptions>
+                  <charset>UTF-8</charset>
+                  <encoding>UTF-8</encoding>
+                  <docencoding>UTF-8</docencoding>
+                  <breakiterator>true</breakiterator>
+                  <version>true</version>
+                  <author>true</author>
+                  <keywords>true</keywords>
+                  <excludePackageNames>net.sf.jnetlib.*:cern.*:corejava</excludePackageNames>
+                </configuration>
+              </plugin>
+              <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jxr-plugin</artifactId>
+                <version>2.3</version>
+                <configuration>
+                  <aggregate>true</aggregate>
+                  <linkJavadoc>true</linkJavadoc>
+                </configuration>
+              </plugin>
+            </reportPlugins>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <repositories>
+    <!-- Maven repo2 mirror -->
+    <repository>
+      <id>central2</id>
+      <name>central2</name>
+      <url>${nexusproxy}/repositories/central2/</url>
+    </repository>
+    <!-- Maven repo1 mirror -->
+    <repository>
+      <id>central</id>
+      <name>central</name>
+      <url>${nexusproxy}/repositories/central/</url>
+    </repository>
+    <!-- Third Packages hosted in local maven because not available in
+         other places -->
+    <repository>
+      <id>thirdparty</id>
+      <name>thirdparty</name>
+      <url>${nexusproxy}/repositories/thirdparty</url>
+    </repository>
+  </repositories>
+  <distributionManagement>
+    <!-- OpenDayLight Released artifact -->
+    <repository>
+      <id>opendaylight-release</id>
+      <url>${nexusproxy}/repositories/opendaylight.release/</url>
+    </repository>
+    <!-- OpenDayLight Snapshot artifact -->
+    <snapshotRepository>
+      <id>opendaylight-snapshot</id>
+      <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
+    </snapshotRepository>
+    <!-- Site deployment -->
+    <site>
+      <id>website</id>
+      <url>${sitedeploy}</url>
+    </site>
+  </distributionManagement>
+</project>
diff --git a/third-party/openflowj_netty/LICENSE b/third-party/openflowj_netty/LICENSE
new file mode 100644 (file)
index 0000000..ee6da46
--- /dev/null
@@ -0,0 +1,29 @@
+Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+University
+
+We are making the OpenFlow specification and associated documentation
+(Software) available for public use and benefit with the expectation that
+others will use, modify and enhance the Software and contribute those
+enhancements back to the community. However, since we would like to make the
+Software available for broadest use, with as few restrictions as possible
+permission is hereby granted, free of charge, to any person obtaining a copy of
+this Software to deal in the Software under the copyrights without restriction,
+including without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to permit
+persons to whom the Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+The name and trademarks of copyright holder(s) may NOT be used in advertising
+or publicity pertaining to the Software or any derivatives without specific,
+written prior permission.
diff --git a/third-party/openflowj_netty/Makefile b/third-party/openflowj_netty/Makefile
new file mode 100644 (file)
index 0000000..b803071
--- /dev/null
@@ -0,0 +1,19 @@
+# Because I am old and crotchety and my fingers can't stop from running 
+#      `make` commands
+all:
+       ant
+
+run:
+       ant run
+
+doc: 
+       ant javadoc
+
+tests:
+       ant tests
+
+count: 
+       @find . -name \*.java | xargs wc -l | sort -n
+
+clean:
+       ant clean
diff --git a/third-party/openflowj_netty/README b/third-party/openflowj_netty/README
new file mode 100644 (file)
index 0000000..6fffebe
--- /dev/null
@@ -0,0 +1,16 @@
+OpenFlow Java - v1.0.0 
+
+A Java implementation of low-level OpenFlow packet marshalling/unmarshalling
+and IO operations. Implements v1.0 of the OpenFlow specification at
+http://www.openflow.org.
+
+    - David Erickson (daviderickson@cs.stanford.edu)
+    - Rob Sherwood (rob.sherwood@stanford.edu)
+
+Building requires Maven 2.x+ (http://maven.apache.org/).
+
+To build:
+    mvn package
+
+To build javadocs:
+    mvn javadoc:javadoc
diff --git a/third-party/openflowj_netty/eclipse_codestyle.xml b/third-party/openflowj_netty/eclipse_codestyle.xml
new file mode 100644 (file)
index 0000000..6b661c6
--- /dev/null
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="11">
+<profile kind="CodeFormatterProfile" name="OpenFlowJ" version="11">
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+</profile>
+</profiles>
diff --git a/third-party/openflowj_netty/lib/commons-cli-1.2.jar b/third-party/openflowj_netty/lib/commons-cli-1.2.jar
new file mode 100644 (file)
index 0000000..ce4b9ff
Binary files /dev/null and b/third-party/openflowj_netty/lib/commons-cli-1.2.jar differ
diff --git a/third-party/openflowj_netty/lib/junit-4.8.1.jar b/third-party/openflowj_netty/lib/junit-4.8.1.jar
new file mode 100644 (file)
index 0000000..524cd65
Binary files /dev/null and b/third-party/openflowj_netty/lib/junit-4.8.1.jar differ
diff --git a/third-party/openflowj_netty/pom.xml b/third-party/openflowj_netty/pom.xml
new file mode 100644 (file)
index 0000000..7907364
--- /dev/null
@@ -0,0 +1,120 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.controller.thirdparty</groupId>
+  <artifactId>org.openflow.openflowj_netty</artifactId>
+  <version>1.0.2-SNAPSHOT</version>
+  <name>OpenFlow Java</name>
+  <description>A Java implemention of the OpenFlow v1.0 protocol</description>
+
+  <!-- Get some common settings for the project we are using it in -->
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.thirdparty</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+    <relativePath>../commons/thirdparty</relativePath>
+  </parent>
+  
+  <developers>
+    <developer>
+      <name>David Erickson</name>
+      <email>daviderickson@cs.stanford.edu</email>
+    </developer>
+    <developer>
+      <name>Rob Sherwood</name>
+      <email>rob.sherwood@stanford.edu</email>
+    </developer>
+  </developers>
+  <packaging>bundle</packaging>
+  <url>http://www.openflow.org</url>
+  <licenses>
+    <license>
+      <name>The OpenFlow License</name>
+      <url>http://www.openflowswitch.org/wp/legal/</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <scm>
+    <connection>scm:git://gitosis.stanford.edu:openflowj.git</connection>
+    <url>https://openflow.stanford.edu/fisheye/browse/OpenFlowJ</url>
+  </scm>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+  <!-- For GPG release signing, use mvn release:perform -->
+  <profiles>
+    <profile>
+      <id>release-sign-artifacts</id>
+      <activation>
+        <property>
+          <name>performRelease</name>
+          <value>true</value>
+        </property>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-gpg-plugin</artifactId>
+            <version>1.1</version>
+            <executions>
+              <execution>
+                <id>sign-artifacts</id>
+                <phase>verify</phase>
+                <goals>
+                  <goal>sign</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <mavenExecutorId>forked-path</mavenExecutorId>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+  <build>
+    <plugins>
+    <plugin>
+       <groupId>org.apache.felix</groupId>
+       <artifactId>maven-bundle-plugin</artifactId>
+       <version>2.3.6</version>
+       <extensions>true</extensions>
+       <configuration>
+         <instructions>
+               <Import-Package>
+                 org.jboss.netty.*
+               </Import-Package>
+           <Export-Package>
+             org.openflow.*
+           </Export-Package>
+         </instructions>
+       </configuration>
+      </plugin>
+      <plugin>
+       <groupId>org.apache.maven.plugins</groupId>
+       <artifactId>maven-compiler-plugin</artifactId>
+       <version>2.3.2</version>
+       <configuration>
+         <source>1.6</source>
+         <target>1.6</target>
+       </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.netty</groupId>
+      <artifactId>netty</artifactId>
+      <version>3.2.6.Final</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/Instantiable.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/Instantiable.java
new file mode 100644 (file)
index 0000000..1358ba7
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFBarrierReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFBarrierReply.java
new file mode 100644 (file)
index 0000000..a79a15f
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFBarrierRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFBarrierRequest.java
new file mode 100644 (file)
index 0000000..9992186
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFEchoReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFEchoReply.java
new file mode 100644 (file)
index 0000000..3e282a7
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFEchoRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFEchoRequest.java
new file mode 100644 (file)
index 0000000..295a397
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFError.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFError.java
new file mode 100644 (file)
index 0000000..df7b236
--- /dev/null
@@ -0,0 +1,325 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFeaturesReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFeaturesReply.java
new file mode 100644 (file)
index 0000000..ebd82b5
--- /dev/null
@@ -0,0 +1,257 @@
+/**
+*    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 org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.util.U16;
+
+
+/**
+ * Represents a features reply message
+ * @author David Erickson (daviderickson@cs.stanford.edu)
+ *
+ */
+
+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
+     */
+    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFeaturesRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFeaturesRequest.java
new file mode 100644 (file)
index 0000000..0a89e4f
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFlowMod.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFlowMod.java
new file mode 100644 (file)
index 0000000..06ef547
--- /dev/null
@@ -0,0 +1,389 @@
+/**
+*    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((OFAction) 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=" + cookie + ", flags=" + flags + ", hardTimeout="
+                + hardTimeout + ", idleTimeout=" + idleTimeout + ", match="
+                + match + ", outPort=" + outPort + ", priority=" + priority
+                + ", length=" + length + ", type=" + type + ", version="
+                + version + ", xid=" + xid + "]";
+    }
+}
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFlowRemoved.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFFlowRemoved.java
new file mode 100644 (file)
index 0000000..3357006
--- /dev/null
@@ -0,0 +1,294 @@
+/**
+*    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 = (int)(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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFGetConfigReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFGetConfigReply.java
new file mode 100644 (file)
index 0000000..257867a
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFGetConfigRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFGetConfigRequest.java
new file mode 100644 (file)
index 0000000..85c7499
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFHello.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFHello.java
new file mode 100644 (file)
index 0000000..e702ca4
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatch.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatch.java
new file mode 100644 (file)
index 0000000..91930f1
--- /dev/null
@@ -0,0 +1,1040 @@
+/**
+ *    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 org.jboss.netty.buffer.ChannelBuffer;
+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)
+ */
+public class OFMatch implements Cloneable, Serializable {
+
+    /**
+     *
+     */
+       
+       public static final short VLAN_UNTAGGED = (short)0xffff;
+       
+    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 = 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:
+                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:
+                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);
+        }
+    }
+
+    /**
+     * 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 + "]";
+    }
+
+    /**
+     * 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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatchBeanInfo.java
new file mode 100644 (file)
index 0000000..16a813f
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+*    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) {
+                e.printStackTrace();
+                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) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        } catch (NoSuchMethodException e) {
+            e.printStackTrace();
+            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) {
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        } catch (NoSuchMethodException e) {
+            e.printStackTrace();
+            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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMatchWithSwDpid.java
new file mode 100644 (file)
index 0000000..0caf9ff
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ *    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 + "]";
+    }
+}
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMessage.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMessage.java
new file mode 100644 (file)
index 0000000..767b7d1
--- /dev/null
@@ -0,0 +1,324 @@
+/**
+*    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 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) {
+
+        
+       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());
+
+                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(" ]");
+
+
+                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();
+
+    }
+    */
+
+    
+    // Check if this is really required
+    /*
+    public static byte[] getData(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
+        return OFMessage.getDataAsString(sw, msg, cntx).getBytes();
+    }
+    */
+}
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMessageContextStore.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFMessageContextStore.java
new file mode 100644 (file)
index 0000000..b60aa1c
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketIn.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketIn.java
new file mode 100644 (file)
index 0000000..c37c918
--- /dev/null
@@ -0,0 +1,211 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketOut.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketOut.java
new file mode 100644 (file)
index 0000000..ef4aa61
--- /dev/null
@@ -0,0 +1,260 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketQueue.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPacketQueue.java
new file mode 100644 (file)
index 0000000..e8de1af
--- /dev/null
@@ -0,0 +1,142 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPhysicalPort.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPhysicalPort.java
new file mode 100644 (file)
index 0000000..da0da61
--- /dev/null
@@ -0,0 +1,465 @@
+/**
+*    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 org.jboss.netty.buffer.ChannelBuffer;
+
+/**
+ * Represents ofp_phy_port
+ * @author David Erickson (daviderickson@cs.stanford.edu) - Mar 25, 2010
+ */
+public class OFPhysicalPort {
+    public static int MINIMUM_LENGTH = 48;
+    public static int OFP_ETH_ALEN = 6;
+
+    public enum OFPortConfig {
+        OFPPC_PORT_DOWN    (1 << 0) {
+            public String toString() {
+                return "port-down (0x1)";
+            }
+        },
+        OFPPC_NO_STP       (1 << 1) {
+            public String toString() {
+                return "no-stp (0x2)";
+            }
+        },
+        OFPPC_NO_RECV      (1 << 2) {
+            public String toString() {
+                return "no-recv (0x4)";
+            }
+        },
+        OFPPC_NO_RECV_STP  (1 << 3) {
+            public String toString() {
+                return "no-recv-stp (0x8)";
+            }
+        },
+        OFPPC_NO_FLOOD     (1 << 4) {
+            public String toString() {
+                return "no-flood (0x10)";
+            }
+        },
+        OFPPC_NO_FWD       (1 << 5) {
+            public String toString() {
+                return "no-fwd (0x20)";
+            }
+        },
+        OFPPC_NO_PACKET_IN (1 << 6) {
+            public String toString() {
+                return "no-pkt-in (0x40)";
+            }
+        };
+
+        protected int value;
+
+        private OFPortConfig(int value) {
+            this.value = value;
+        }
+
+        /**
+         * @return the value
+         */
+        public int getValue() {
+            return value;
+        }
+    }
+
+    public enum OFPortState {
+        OFPPS_LINK_DOWN   (1 << 0) {
+            public String toString() {
+                return "link-down (0x1)";
+            }
+        },
+        OFPPS_STP_LISTEN  (0 << 8) {
+            public String toString() {
+                return "listen (0x0)";
+            }
+        },
+        OFPPS_STP_LEARN   (1 << 8) {
+            public String toString() {
+                return "learn-no-relay (0x100)";
+            }
+        },
+        OFPPS_STP_FORWARD (2 << 8) {
+            public String toString() {
+                return "forward (0x200)";
+            }
+        },
+        OFPPS_STP_BLOCK   (3 << 8) {
+            public String toString() {
+                return "block-broadcast (0x300)";
+            }
+        },
+        OFPPS_STP_MASK    (3 << 8) {
+            public String toString() {
+                return "block-broadcast (0x300)";
+            }
+        };
+
+        protected int value;
+
+        private OFPortState(int value) {
+            this.value = value;
+        }
+
+        /**
+         * @return the value
+         */
+        public int getValue() {
+            return value;
+        }
+    }
+
+    public enum OFPortFeatures {
+        OFPPF_10MB_HD    (1 << 0) {
+            public String toString() {
+                return "10mb-hd (0x1)";
+            }
+        },
+        OFPPF_10MB_FD    (1 << 1) {
+            public String toString() {
+                return "10mb-fd (0x2)";
+            }
+        },
+        OFPPF_100MB_HD   (1 << 2) {
+            public String toString() {
+                return "100mb-hd (0x4)";
+            }
+        },
+        OFPPF_100MB_FD   (1 << 3) {
+            public String toString() {
+                return "100mb-fd (0x8)";
+            }
+        },
+        OFPPF_1GB_HD     (1 << 4) {
+            public String toString() {
+                return "1gb-hd (0x10)";
+            }
+        },
+        OFPPF_1GB_FD     (1 << 5) {
+            public String toString() {
+                return "1gb-fd (0x20)";
+            }
+        },
+        OFPPF_10GB_FD    (1 << 6) {
+            public String toString() {
+                return "10gb-fd (0x40)";
+            }
+        },
+        OFPPF_COPPER     (1 << 7) {
+            public String toString() {
+                return "copper (0x80)";
+            }
+        },
+        OFPPF_FIBER      (1 << 8) {
+            public String toString() {
+                return "fiber (0x100)";
+            }
+        },
+        OFPPF_AUTONEG    (1 << 9) {
+            public String toString() {
+                return "autoneg (0x200)";
+            }
+        },
+        OFPPF_PAUSE      (1 << 10) {
+            public String toString() {
+                return "pause (0x400)";
+            }
+        },
+        OFPPF_PAUSE_ASYM (1 << 11) {
+            public String toString() {
+                return "pause-asym (0x800)";
+            }
+        };
+
+        protected int value;
+
+        private OFPortFeatures(int value) {
+            this.value = value;
+        }
+
+        /**
+         * @return the value
+         */
+        public int getValue() {
+            return value;
+        }
+    }
+
+    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
+     */
+    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 != 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;
+    }
+}
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPort.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPort.java
new file mode 100644 (file)
index 0000000..93301bc
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPortMod.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPortMod.java
new file mode 100644 (file)
index 0000000..876e856
--- /dev/null
@@ -0,0 +1,182 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPortStatus.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFPortStatus.java
new file mode 100644 (file)
index 0000000..8bde6e7
--- /dev/null
@@ -0,0 +1,126 @@
+/**
+*    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,
+        OFPPR_DELETE,
+        OFPPR_MODIFY
+    }
+
+    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueGetConfigReply.java
new file mode 100644 (file)
index 0000000..62be90d
--- /dev/null
@@ -0,0 +1,125 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueGetConfigRequest.java
new file mode 100644 (file)
index 0000000..cbb4a37
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueProp.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFQueueProp.java
new file mode 100644 (file)
index 0000000..2e12224
--- /dev/null
@@ -0,0 +1,175 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFSetConfig.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFSetConfig.java
new file mode 100644 (file)
index 0000000..4b23564
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsMessageBase.java
new file mode 100644 (file)
index 0000000..e5a9c01
--- /dev/null
@@ -0,0 +1,180 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsReply.java
new file mode 100644 (file)
index 0000000..ddc7267
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFStatisticsRequest.java
new file mode 100644 (file)
index 0000000..d1d8010
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFSwitchConfig.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFSwitchConfig.java
new file mode 100644 (file)
index 0000000..e04e3fa
--- /dev/null
@@ -0,0 +1,118 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFType.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFType.java
new file mode 100644 (file)
index 0000000..f1c81e2
--- /dev/null
@@ -0,0 +1,249 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFVendor.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/OFVendor.java
new file mode 100644 (file)
index 0000000..8ecb862
--- /dev/null
@@ -0,0 +1,131 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/Wildcards.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/Wildcards.java
new file mode 100644 (file)
index 0000000..fbda858
--- /dev/null
@@ -0,0 +1,527 @@
+/**
+ *    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;
+
+
+/**
+ * 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;
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFAction.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFAction.java
new file mode 100644 (file)
index 0000000..57b5dc1
--- /dev/null
@@ -0,0 +1,173 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayer.java
new file mode 100644 (file)
index 0000000..a6eae63
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+*    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 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
+     */
+    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;
+    }
+}
\ No newline at end of file
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayerDestination.java
new file mode 100644 (file)
index 0000000..48b8d0f
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionDataLayerSource.java
new file mode 100644 (file)
index 0000000..e04561c
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionEnqueue.java
new file mode 100644 (file)
index 0000000..0ec2fa3
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+*    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;
+    }
+}
\ No newline at end of file
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerAddress.java
new file mode 100644 (file)
index 0000000..dc65ae9
--- /dev/null
@@ -0,0 +1,86 @@
+/**
+*    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_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;
+    }
+}
\ No newline at end of file
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerDestination.java
new file mode 100644 (file)
index 0000000..13c14ff
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkLayerSource.java
new file mode 100644 (file)
index 0000000..ef1d005
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionNetworkTypeOfService.java
new file mode 100644 (file)
index 0000000..0d38180
--- /dev/null
@@ -0,0 +1,101 @@
+/**
+*    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;
+    }
+}
\ No newline at end of file
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionOutput.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionOutput.java
new file mode 100644 (file)
index 0000000..b9521d0
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+*    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;
+import org.openflow.util.U16;
+
+/**
+ * @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() {
+        return "OFActionOutput [maxLength=" + maxLength + ", port=" + U16.f(port)
+                + ", length=" + length + ", type=" + type + "]";
+    }
+}
\ No newline at end of file
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionStripVirtualLan.java
new file mode 100644 (file)
index 0000000..7d6b849
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+*    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);
+    }
+}
\ No newline at end of file
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayer.java
new file mode 100644 (file)
index 0000000..0bc09c9
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+*    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;
+    }
+}
\ No newline at end of file
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayerDestination.java
new file mode 100644 (file)
index 0000000..7e7b0f1
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionTransportLayerSource.java
new file mode 100644 (file)
index 0000000..385aa53
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionType.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionType.java
new file mode 100644 (file)
index 0000000..1822917
--- /dev/null
@@ -0,0 +1,203 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVendor.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVendor.java
new file mode 100644 (file)
index 0000000..5860ef1
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVendorGeneric.java
new file mode 100644 (file)
index 0000000..4f7859f
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVirtualLanIdentifier.java
new file mode 100644 (file)
index 0000000..5bd0e0b
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/action/OFActionVirtualLanPriorityCodePoint.java
new file mode 100644 (file)
index 0000000..9202df3
--- /dev/null
@@ -0,0 +1,100 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/BasicFactory.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/BasicFactory.java
new file mode 100644 (file)
index 0000000..b61aa72
--- /dev/null
@@ -0,0 +1,344 @@
+/**
+*    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.nio.ByteBuffer;
+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 class BasicFactory implements OFMessageFactory, OFActionFactory,
+        OFStatisticsFactory, OFVendorDataFactory {
+
+    private final OFVendorActionRegistry vendorActionRegistry;
+
+    public BasicFactory() {
+        vendorActionRegistry = OFVendorActionRegistry.getInstance();
+    }
+
+    /**
+     * 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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/MessageParseException.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/MessageParseException.java
new file mode 100644 (file)
index 0000000..20f381e
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ *    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFActionFactory.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFActionFactory.java
new file mode 100644 (file)
index 0000000..c3cd062
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFActionFactoryAware.java
new file mode 100644 (file)
index 0000000..a97a95c
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFMessageFactory.java
new file mode 100644 (file)
index 0000000..8bb7045
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFMessageFactoryAware.java
new file mode 100644 (file)
index 0000000..adb1421
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFStatisticsFactory.java
new file mode 100644 (file)
index 0000000..32eb3cb
--- /dev/null
@@ -0,0 +1,72 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFStatisticsFactoryAware.java
new file mode 100644 (file)
index 0000000..52ab09a
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorActionFactory.java
new file mode 100644 (file)
index 0000000..eb89810
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+ *    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorActionRegistry.java
new file mode 100644 (file)
index 0000000..1f55681
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+ *    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorDataFactory.java
new file mode 100644 (file)
index 0000000..d754a4a
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/factory/OFVendorDataFactoryAware.java
new file mode 100644 (file)
index 0000000..23614b0
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsReply.java
new file mode 100644 (file)
index 0000000..b5a486c
--- /dev/null
@@ -0,0 +1,128 @@
+/**
+*    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_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
+    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFAggregateStatisticsRequest.java
new file mode 100644 (file)
index 0000000..f41a4f1
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFDescriptionStatistics.java
new file mode 100644 (file)
index 0000000..86ad782
--- /dev/null
@@ -0,0 +1,225 @@
+/**
+*    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_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;
+
+    /**
+     * @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
+    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsReply.java
new file mode 100644 (file)
index 0000000..0570779
--- /dev/null
@@ -0,0 +1,357 @@
+/**
+*    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 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
+    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=" + 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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFFlowStatisticsRequest.java
new file mode 100644 (file)
index 0000000..b21de0c
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsReply.java
new file mode 100644 (file)
index 0000000..02b97b3
--- /dev/null
@@ -0,0 +1,351 @@
+/**
+*    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 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
+     */
+    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
+    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFPortStatisticsRequest.java
new file mode 100644 (file)
index 0000000..c07a895
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsReply.java
new file mode 100644 (file)
index 0000000..7d0238a
--- /dev/null
@@ -0,0 +1,173 @@
+/**
+*    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 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
+    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFQueueStatisticsRequest.java
new file mode 100644 (file)
index 0000000..3331453
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFStatistics.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFStatistics.java
new file mode 100644 (file)
index 0000000..5e8f4dd
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFStatisticsType.java
new file mode 100644 (file)
index 0000000..f2b9e30
--- /dev/null
@@ -0,0 +1,317 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFTableStatistics.java
new file mode 100644 (file)
index 0000000..9e6d34e
--- /dev/null
@@ -0,0 +1,223 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/statistics/OFVendorStatistics.java
new file mode 100644 (file)
index 0000000..0257a6a
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFBasicVendorDataType.java
new file mode 100644 (file)
index 0000000..1f0e14b
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFBasicVendorId.java
new file mode 100644 (file)
index 0000000..5f789dc
--- /dev/null
@@ -0,0 +1,162 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFByteArrayVendorData.java
new file mode 100644 (file)
index 0000000..08fa003
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorData.java
new file mode 100644 (file)
index 0000000..6dfb4e6
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorDataType.java
new file mode 100644 (file)
index 0000000..ecae482
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorId.java b/third-party/openflowj_netty/src/main/java/org/openflow/protocol/vendor/OFVendorId.java
new file mode 100644 (file)
index 0000000..f0af8a7
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/util/HexString.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/HexString.java
new file mode 100644 (file)
index 0000000..b562824
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/util/IProducer.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/IProducer.java
new file mode 100644 (file)
index 0000000..52ae79a
--- /dev/null
@@ -0,0 +1,9 @@
+package org.openflow.util;
+
+public interface IProducer {
+
+    public void registerConsumer(Class<?> iface, Object anObj);
+
+    public void deregisterConsumer(Class<?> iface, Object anObj);
+
+}
diff --git a/third-party/openflowj_netty/src/main/java/org/openflow/util/LRULinkedHashMap.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/LRULinkedHashMap.java
new file mode 100644 (file)
index 0000000..7f05381
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/util/ProducerConsumer.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/ProducerConsumer.java
new file mode 100644 (file)
index 0000000..f2244ef
--- /dev/null
@@ -0,0 +1,223 @@
+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/third-party/openflowj_netty/src/main/java/org/openflow/util/StringByteSerializer.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/StringByteSerializer.java
new file mode 100644 (file)
index 0000000..9287fd2
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/util/U16.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/U16.java
new file mode 100644 (file)
index 0000000..0d8917d
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/util/U32.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/U32.java
new file mode 100644 (file)
index 0000000..3aab400
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/util/U64.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/U64.java
new file mode 100644 (file)
index 0000000..c6ae0f7
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/util/U8.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/U8.java
new file mode 100644 (file)
index 0000000..0b575ad
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/util/Unsigned.java b/third-party/openflowj_netty/src/main/java/org/openflow/util/Unsigned.java
new file mode 100644 (file)
index 0000000..0754a3f
--- /dev/null
@@ -0,0 +1,212 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorData.java
new file mode 100644 (file)
index 0000000..687d544
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFNiciraVendorExtensions.java
new file mode 100644 (file)
index 0000000..98f88b2
--- /dev/null
@@ -0,0 +1,30 @@
+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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleReplyVendorData.java
new file mode 100644 (file)
index 0000000..fa28c71
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleRequestVendorData.java
new file mode 100644 (file)
index 0000000..e7dbe71
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/nicira/OFRoleVendorData.java
new file mode 100644 (file)
index 0000000..e7c8bf2
--- /dev/null
@@ -0,0 +1,113 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorData.java
new file mode 100644 (file)
index 0000000..9be821f
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFOpenFlowVendorExtensions.java
new file mode 100644 (file)
index 0000000..3fa1029
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueDeleteVendorData.java
new file mode 100644 (file)
index 0000000..4fc52ba
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueModifyVendorData.java
new file mode 100644 (file)
index 0000000..0d2f31b
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+*    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/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java b/third-party/openflowj_netty/src/main/java/org/openflow/vendor/openflow/OFQueueVendorData.java
new file mode 100644 (file)
index 0000000..eeae9aa
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/BasicFactoryTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/BasicFactoryTest.java
new file mode 100644 (file)
index 0000000..312fcd3
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+*    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 = new BasicFactory();
+        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 = new BasicFactory();
+        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 = new BasicFactory();
+        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 = new BasicFactory();
+        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 = new BasicFactory();
+        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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFActionTypeTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFActionTypeTest.java
new file mode 100644 (file)
index 0000000..ed8386c
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFBarrierReplyTest.java
new file mode 100644 (file)
index 0000000..7e447bb
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFBarrierRequestTest.java
new file mode 100644 (file)
index 0000000..3aa9cb4
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFErrorTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFErrorTest.java
new file mode 100644 (file)
index 0000000..45d5257
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+*    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((short) 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((short) 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((short) 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 = new BasicFactory();
+        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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFFeaturesReplyTest.java
new file mode 100644 (file)
index 0000000..62e491a
--- /dev/null
@@ -0,0 +1,62 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFFlowRemovedTest.java
new file mode 100644 (file)
index 0000000..11746e7
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFGetConfigReplyTest.java
new file mode 100644 (file)
index 0000000..c1f1f67
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFGetConfigRequestTest.java
new file mode 100644 (file)
index 0000000..94d9036
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFMatchTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFMatchTest.java
new file mode 100644 (file)
index 0000000..fd7863a
--- /dev/null
@@ -0,0 +1,92 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFMessageContextStoreTest.java
new file mode 100644 (file)
index 0000000..60a9e73
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPacketOutTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPacketOutTest.java
new file mode 100644 (file)
index 0000000..55b5455
--- /dev/null
@@ -0,0 +1,45 @@
+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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPortConfigTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPortConfigTest.java
new file mode 100644 (file)
index 0000000..9b115eb
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPortStatusTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFPortStatusTest.java
new file mode 100644 (file)
index 0000000..4fab64e
--- /dev/null
@@ -0,0 +1,44 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFSetConfigTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFSetConfigTest.java
new file mode 100644 (file)
index 0000000..2a9e86f
--- /dev/null
@@ -0,0 +1,38 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsReplyTest.java
new file mode 100644 (file)
index 0000000..50bac8f
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+*    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 = new BasicFactory();
+        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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsRequestTest.java
new file mode 100644 (file)
index 0000000..74af6f4
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+*    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 = new BasicFactory();
+        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 = new BasicFactory();
+        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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFStatisticsTypeTest.java
new file mode 100644 (file)
index 0000000..d44ef7f
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFTypeTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFTypeTest.java
new file mode 100644 (file)
index 0000000..c6bf0a3
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFVendorTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/OFVendorTest.java
new file mode 100644 (file)
index 0000000..b85a915
--- /dev/null
@@ -0,0 +1,215 @@
+/**
+*    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;
+        
+        public int getLength() {
+            return 4;
+        }
+        
+        public void readFrom(ChannelBuffer data, int length) {
+            dataType = data.readInt();
+        }
+        
+        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;
+        }
+        
+        public int getLength() {
+            return 8;
+        }
+        
+        public void readFrom(ChannelBuffer data, int length) {
+            super.readFrom(data, length);
+            flags = data.readShort();
+            value = data.readShort();
+
+        }
+        public void writeTo(ChannelBuffer data) {
+            super.writeTo(data);
+            data.writeShort(flags);
+            data.writeShort(value);
+        }
+        
+        public static Instantiable<OFVendorData> getInstantiable() {
+            return new Instantiable<OFVendorData>() {
+                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;
+        }
+        
+        public int getLength() {
+            return 12;
+        }
+        
+        public void readFrom(ChannelBuffer data, int length) {
+            super.readFrom(data, length);
+            type = data.readShort();
+            subtype = data.readShort();
+
+        }
+        public void writeTo(ChannelBuffer data) {
+            super.writeTo(data);
+            data.writeShort(type);
+            data.writeShort(subtype);
+        }
+        
+        public static Instantiable<OFVendorData> getInstantiable() {
+            return new Instantiable<OFVendorData>() {
+                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(new BasicFactory());
+        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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/WildcardsTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/WildcardsTest.java
new file mode 100644 (file)
index 0000000..5bf8d12
--- /dev/null
@@ -0,0 +1,162 @@
+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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/MockVendorAction.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/MockVendorAction.java
new file mode 100644 (file)
index 0000000..49b69fb
--- /dev/null
@@ -0,0 +1,41 @@
+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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/MockVendorActionFactory.java
new file mode 100644 (file)
index 0000000..bbc254c
--- /dev/null
@@ -0,0 +1,15 @@
+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/third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/protocol/action/OFVendorActionRegistryTest.java
new file mode 100644 (file)
index 0000000..31ad675
--- /dev/null
@@ -0,0 +1,17 @@
+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/third-party/openflowj_netty/src/test/java/org/openflow/util/HexStringTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/util/HexStringTest.java
new file mode 100644 (file)
index 0000000..a8f8ba4
--- /dev/null
@@ -0,0 +1,88 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/util/OFTestCase.java b/third-party/openflowj_netty/src/test/java/org/openflow/util/OFTestCase.java
new file mode 100644 (file)
index 0000000..5132c2c
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+*    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 = new BasicFactory();
+    }
+
+    public void test() throws Exception {
+    }
+}
diff --git a/third-party/openflowj_netty/src/test/java/org/openflow/util/U16Test.java b/third-party/openflowj_netty/src/test/java/org/openflow/util/U16Test.java
new file mode 100644 (file)
index 0000000..ba87e7b
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/util/U32Test.java b/third-party/openflowj_netty/src/test/java/org/openflow/util/U32Test.java
new file mode 100644 (file)
index 0000000..223c103
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/util/U64Test.java b/third-party/openflowj_netty/src/test/java/org/openflow/util/U64Test.java
new file mode 100644 (file)
index 0000000..0a97e30
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/util/U8Test.java b/third-party/openflowj_netty/src/test/java/org/openflow/util/U8Test.java
new file mode 100644 (file)
index 0000000..2c06c4d
--- /dev/null
@@ -0,0 +1,32 @@
+/**
+*    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/third-party/openflowj_netty/src/test/java/org/openflow/util/UnsignedTest.java b/third-party/openflowj_netty/src/test/java/org/openflow/util/UnsignedTest.java
new file mode 100644 (file)
index 0000000..7cdf739
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+*    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);
+    }
+  }
+}