Added cubby-holes for new projects.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..411d0ed
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+*~
+*.class
+.classpath
+.project
+.pydevproject
+.settings
+.javacp*
+target
+*.iml
+.idea
diff --git a/cli/pom.xml b/cli/pom.xml
new file mode 100644
index 0000000..80e173d
--- /dev/null
+++ b/cli/pom.xml
@@ -0,0 +1,44 @@
+<?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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onos</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-cli</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>ONOS administrative console command-line extensions
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onos-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/cli/src/main/java/org/onlab/onos/cli/AbstractShellCommand.java b/cli/src/main/java/org/onlab/onos/cli/AbstractShellCommand.java
new file mode 100644
index 0000000..aeea443
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/AbstractShellCommand.java
@@ -0,0 +1,24 @@
+package org.onlab.onos.cli;
+
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * Base abstraction of Karaf shell commands.
+ */
+public abstract class AbstractShellCommand extends OsgiCommandSupport {
+
+ /**
+ * Returns the reference to the implementaiton of the specified service.
+ *
+ * @param serviceClass service class
+ * @param <T> type of service
+ * @return service implementation
+ */
+ static <T> T get(Class<T> serviceClass) {
+ BundleContext bc = FrameworkUtil.getBundle(AbstractShellCommand.class).getBundleContext();
+ return bc.getService(bc.getServiceReference(serviceClass));
+ }
+
+}
diff --git a/cli/src/main/java/org/onlab/onos/cli/GreetCommand.java b/cli/src/main/java/org/onlab/onos/cli/GreetCommand.java
new file mode 100644
index 0000000..dd8ae81
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/GreetCommand.java
@@ -0,0 +1,24 @@
+package org.onlab.onos.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.onlab.onos.net.GreetService;
+
+/**
+ * Simple command example to demonstrate use of Karaf shell extensions; shows
+ * use of an optional parameter as well.
+ */
+@Command(scope = "onos", name = "greet", description = "Issues a greeting")
+public class GreetCommand extends OsgiCommandSupport {
+
+ @Argument(index = 0, name = "name", description = "Name to greet",
+ required = false, multiValued = false)
+ String name = "dude";
+
+ @Override
+ protected Object doExecute() throws Exception {
+ System.out.println(getService(GreetService.class).yo(name));
+ return null;
+ }
+}
diff --git a/cli/src/main/java/org/onlab/onos/cli/NameCompleter.java b/cli/src/main/java/org/onlab/onos/cli/NameCompleter.java
new file mode 100644
index 0000000..bdf3f72
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/NameCompleter.java
@@ -0,0 +1,33 @@
+package org.onlab.onos.cli;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onlab.onos.net.GreetService;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Simple example of a command-line parameter completer.
+ * For a more open-ended sets a more efficient implementation would be required.
+ */
+public class NameCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ GreetService greetService = AbstractShellCommand.get(GreetService.class);
+ Iterator<String> it = greetService.names().iterator();
+ SortedSet<String> strings = delegate.getStrings();
+ while (it.hasNext()) {
+ strings.add(it.next());
+ }
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+
+}
diff --git a/cli/src/main/javadoc/org/onlab/onos/cli/package.html b/cli/src/main/javadoc/org/onlab/onos/cli/package.html
new file mode 100644
index 0000000..dacfec0
--- /dev/null
+++ b/cli/src/main/javadoc/org/onlab/onos/cli/package.html
@@ -0,0 +1,3 @@
+<body>
+Administrative console command-line extensions.
+</body>
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
new file mode 100644
index 0000000..5cc83ef
--- /dev/null
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -0,0 +1,14 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.onlab.onos.cli.GreetCommand"/>
+ <completers>
+ <ref component-id="nameCompleter"/>
+ </completers>
+ </command>
+ </command-bundle>
+
+ <bean id="nameCompleter" class="org.onlab.onos.cli.NameCompleter"/>
+
+</blueprint>
diff --git a/features.xml b/features.xml
deleted file mode 100644
index 461d684..0000000
--- a/features.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<!--
- ~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
- ~
- ~ 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
- -->
-
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
- name="net.onrc.onos-1.0.0">
- <repository>mvn:net.onrc.onos/onos-features/1.0.0-SNAPSHOT/xml/features</repository>
-
- <feature name="thirdparty" version="1.0.0"
- description="ONOS 3rd party dependencies">
- <bundle>mvn:com.google.code.findbugs/annotations/2.0.2</bundle>
- <bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
- <bundle>mvn:com.google.guava/guava/17.0</bundle>
- <bundle>mvn:com.google.guava/guava/15.0</bundle>
-
- </feature>
-
- <feature name="base" version="1.0.0"
- description="ONOS Base">
- <feature>scr</feature>
- <feature>thirdparty</feature>
- <bundle>mvn:net.onrc.onos.sb/onos-sb/0.0.1</bundle>
- <bundle>mvn:org.projectfloodlight/openflowj/0.3.6-SNAPSHOT</bundle>
- </feature>
-
-</features>
diff --git a/features/features.xml b/features/features.xml
index 4b8f8cb..1c8f985 100644
--- a/features/features.xml
+++ b/features/features.xml
@@ -1,22 +1,65 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
- name="net.onrc.onos-1.0.0">
- <repository>mvn:net.onrc.onos/onos-features/1.0.0-SNAPSHOT/xml/features</repository>
+ name="onos-1.0.0">
+ <repository>mvn:org.onlab.onos/onos-features/1.0.0-SNAPSHOT/xml/features</repository>
- <feature name="onos-thirdparty" version="1.0.0"
+ <feature name="onos-thirdparty-base" version="1.0.0"
description="ONOS 3rd party dependencies">
- <bundle>mvn:com.google.code.findbugs/annotations/2.0.2</bundle>
+ <bundle>mvn:com.google.guava/guava/17.0</bundle>
<bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
- <bundle>mvn:com.google.guava/guava/17.0</bundle>
- <bundle>mvn:com.google.guava/guava/15.0</bundle>
</feature>
- <feature name="onos-of-ctl" version="1.0.0"
- description="ONOS OpenFlow Libraries & Controller">
+ <feature name="onos-thirdparty-web" version="1.0.0"
+ description="ONOS 3rd party dependencies">
+ <feature>war</feature>
+ <bundle>mvn:com.fasterxml.jackson.core/jackson-core/2.4.2</bundle>
+ <bundle>mvn:com.fasterxml.jackson.core/jackson-annotations/2.4.2</bundle>
+ <bundle>mvn:com.fasterxml.jackson.core/jackson-databind/2.4.2</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-core/1.18.1</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-server/1.18.1</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-servlet/1.18.1</bundle>
+ </feature>
+
+ <feature name="onos-core" version="1.0.0"
+ description="ONOS core components">
<feature>scr</feature>
- <feature>thirdparty</feature>
- <bundle>mvn:net.onrc.onos.sb/onos-sb/0.0.1</bundle>
- <bundle>mvn:org.projectfloodlight/openflowj/0.3.6-SNAPSHOT</bundle>
+ <feature>onos-thirdparty-base</feature>
+ <bundle>mvn:org.onlab.onos/onos-utils-osgi/1.0.0-SNAPSHOT</bundle>
+ <bundle>mvn:org.onlab.onos/onos-utils-rest/1.0.0-SNAPSHOT</bundle>
+
+ <bundle>mvn:org.onlab.onos/onos-api/1.0.0-SNAPSHOT</bundle>
+ <bundle>mvn:org.onlab.onos/onos-core/1.0.0-SNAPSHOT</bundle>
+ </feature>
+
+ <feature name="onos-rest" version="1.0.0"
+ description="ONOS REST API components">
+ <feature>onos-core</feature>
+ <feature>onos-thirdparty-web</feature>
+ <bundle>mvn:org.onlab.onos/onos-rest/1.0.0-SNAPSHOT</bundle>
+ </feature>
+
+ <feature name="onos-gui" version="1.0.0"
+ description="ONOS GUI console components">
+ <feature>onos-core</feature>
+ <feature>onos-thirdparty-web</feature>
+ <bundle>mvn:org.onlab.onos/onos-gui/1.0.0-SNAPSHOT</bundle>
+ </feature>
+
+ <feature name="onos-cli" version="1.0.0"
+ description="ONOS admin command console components">
+ <feature>onos-core</feature>
+ <bundle>mvn:org.onlab.onos/onos-cli/1.0.0-SNAPSHOT</bundle>
+ </feature>
+
+ <feature name="onos-openflow" version="1.0.0"
+ description="ONOS OpenFlow API, Controller & Providers">
+ <feature>onos-core</feature>
+ <bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
+ <bundle>mvn:com.google.guava/guava/15.0</bundle>
+
+ <bundle>mvn:org.onlab.onos/openflow-api/1.0.0-SNAPSHOT</bundle>
+ <bundle>mvn:org.onlab.onos/openflow-ctl/1.0.0-SNAPSHOT</bundle>
+ <bundle>mvn:org.onlab.onos/onos-of-providers/1.0.0-SNAPSHOT</bundle>
</feature>
</features>
diff --git a/features/old-features.xml b/features/old-features.xml
new file mode 100644
index 0000000..46e68ca
--- /dev/null
+++ b/features/old-features.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
+ ~
+ ~ 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
+ -->
+
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ name="net.onrc.onos-1.0.0">
+ <repository>mvn:net.onrc.onos/onos-features/1.0.0-SNAPSHOT/xml/features</repository>
+
+ <feature name="thirdparty" version="1.0.0"
+ description="ONOS 3rd party dependencies">
+ <bundle>mvn:com.google.code.findbugs/annotations/2.0.2</bundle>
+ <bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
+ <bundle>mvn:com.google.guava/guava/17.0</bundle>
+ <bundle>mvn:com.google.guava/guava/15.0</bundle>
+
+ </feature>
+
+ <feature name="base" version="1.0.0"
+ description="ONOS Base">
+ <feature>scr</feature>
+ <feature>thirdparty</feature>
+ <bundle>mvn:net.onrc.onos.sb/onos-sb/0.0.1</bundle>
+ <bundle>mvn:org.projectfloodlight/openflowj/0.3.6-SNAPSHOT</bundle>
+ </feature>
+
+</features>
diff --git a/features/pom.xml b/features/pom.xml
index baf4bf7..e370fc6 100644
--- a/features/pom.xml
+++ b/features/pom.xml
@@ -5,16 +5,15 @@
<modelVersion>4.0.0</modelVersion>
<parent>
- <groupId>net.onrc.onos</groupId>
+ <groupId>org.onlab.onos</groupId>
<artifactId>onos</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-features</artifactId>
- <packaging>jar</packaging>
+ <packaging>pom</packaging>
- <name>onos-features</name>
<description>ONOS Apache Karaf feature definitions</description>
<build>
@@ -22,7 +21,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
- <version>1.3</version>
+ <version>1.9</version>
<executions>
<execution>
<id>attach-artifacts</id>
diff --git a/net/api/pom.xml b/net/api/pom.xml
new file mode 100644
index 0000000..f74d08e
--- /dev/null
+++ b/net/api/pom.xml
@@ -0,0 +1,19 @@
+<?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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onos-net</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-api</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>ONOS network control API</description>
+
+</project>
diff --git a/net/api/src/main/java/net/onrc/onos/api/Description.java b/net/api/src/main/java/net/onrc/onos/api/Description.java
deleted file mode 100644
index 8a3c127..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/Description.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package net.onrc.onos.api;
-
-/**
- * Base abstraction of a piece of information about network elements.
- */
-public interface Description {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/DeviceId.java b/net/api/src/main/java/net/onrc/onos/api/DeviceId.java
deleted file mode 100644
index 2210742..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/DeviceId.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package net.onrc.onos.api;
-
-import java.net.URI;
-
-/**
- * Immutable representaion of a device identity.
- */
-public class DeviceId {
-
- private final URI uri;
-
- public DeviceId(URI uri) {
- this.uri = uri;
- }
-
- /**
- * Returns the backing URI.
- *
- * @return backing device URI
- */
- public URI uri() {
- return uri;
- }
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/PortNumber.java b/net/api/src/main/java/net/onrc/onos/api/PortNumber.java
deleted file mode 100644
index 9a6dddd..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/PortNumber.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package net.onrc.onos.api;
-
-/**
- * Representation of a port number.
- */
-public interface PortNumber {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/Provider.java b/net/api/src/main/java/net/onrc/onos/api/Provider.java
deleted file mode 100644
index 1b38cf4..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/Provider.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api;
-
-/**
- * Abstraction of a provider of information about network environment.
- */
-public interface Provider {
-
- ProviderId id();
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/ProviderBroker.java b/net/api/src/main/java/net/onrc/onos/api/ProviderBroker.java
deleted file mode 100644
index ef2d4dc..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/ProviderBroker.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package net.onrc.onos.api;
-
-/**
- * Broker used for registering/unregistering information providers with the core.
- *
- * @param <T> type of the information provider
- * @param <S> type of the provider service
- */
-public interface ProviderBroker<T extends Provider, S extends ProviderService> {
-
- /**
- * Registers the supplied provider with the core.
- *
- * @param provider provider to be registered
- * @return provider service for injecting information into core
- */
- S register(T provider);
-
- /**
- * Unregisters the supplied provider. As a result the previously issued
- * provider service will be invalidated.
- *
- * @param provider provider to be unregistered
- */
- void unregister(T provider);
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/ProviderId.java b/net/api/src/main/java/net/onrc/onos/api/ProviderId.java
deleted file mode 100644
index 3f29bac..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/ProviderId.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package net.onrc.onos.api;
-
-/**
- * Notion of provider identity.
- */
-public class ProviderId {
-
- private final String id;
-
- public ProviderId(String id) {
- this.id = id;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
-
- ProviderId that = (ProviderId) o;
-
- if (!id.equals(that.id)) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return id.hashCode();
- }
-
- @Override
- public String toString() {
- return "ProviderId{" +
- "id='" + id + '\'' +
- '}';
- }
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/ProviderService.java b/net/api/src/main/java/net/onrc/onos/api/ProviderService.java
deleted file mode 100644
index add3366..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/ProviderService.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package net.onrc.onos.api;
-
-/**
- * Abstraction of a service through which providers can inject information
- * about the network environment into the core.
- */
-public interface ProviderService {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/device/DeviceDescription.java b/net/api/src/main/java/net/onrc/onos/api/device/DeviceDescription.java
deleted file mode 100644
index ef9a694..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/device/DeviceDescription.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.onrc.onos.api.device;
-
-import net.onrc.onos.api.Description;
-
-import java.net.URI;
-
-/**
- * Carrier of immutable information about a device.
- */
-public interface DeviceDescription extends Description {
-
- /**
- * Protocol/provider specific URI that can be used to encode the identity
- * information required to communicate with the device externally, e.g.
- * datapath ID.
- *
- * @return provider specific URI for the device
- */
- URI deviceURI();
-
-}
\ No newline at end of file
diff --git a/net/api/src/main/java/net/onrc/onos/api/device/DeviceProvider.java b/net/api/src/main/java/net/onrc/onos/api/device/DeviceProvider.java
deleted file mode 100644
index c93cab5..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/device/DeviceProvider.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package net.onrc.onos.api.device;
-
-import net.onrc.onos.api.Provider;
-
-/**
- * Abstraction of a device information provider.
- */
-public interface DeviceProvider extends Provider {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/device/DeviceProviderBroker.java b/net/api/src/main/java/net/onrc/onos/api/device/DeviceProviderBroker.java
deleted file mode 100644
index fdbe322..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/device/DeviceProviderBroker.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api.device;
-
-import net.onrc.onos.api.ProviderBroker;
-
-/**
- * Abstraction of a device provider brokerage.
- */
-public interface DeviceProviderBroker
- extends ProviderBroker<DeviceProvider, DeviceProviderService> {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/device/DeviceProviderService.java b/net/api/src/main/java/net/onrc/onos/api/device/DeviceProviderService.java
deleted file mode 100644
index b0a33a6..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/device/DeviceProviderService.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package net.onrc.onos.api.device;
-
-import net.onrc.onos.api.ProviderService;
-
-import java.util.List;
-
-/**
- * Service through which device providers can inject device information into
- * the core.
- */
-public interface DeviceProviderService extends ProviderService {
-
- // TODO: define suspend and remove actions on the mezzanine administrative API
-
- /**
- * Signals the core that a device has connected or has been detected somehow.
- *
- * @param deviceDescription information about network device
- */
- void deviceConnected(DeviceDescription deviceDescription);
-
- /**
- * Signals the core that a device has disconnected or is no longer reachable.
- *
- * @param deviceDescription device to be removed
- */
- void deviceDisconnected(DeviceDescription deviceDescription);
-
- /**
- * Sends information about all ports of a device. It is up to the core to
- * determine what has changed.
- *
- * @param ports list of device ports
- */
- void updatePorts(List<PortDescription> ports);
-
- /**
- * Used to notify the core about port status change of a single port.
- *
- * @param port description of the port that changed
- */
- void portStatusChanged(PortDescription port);
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/device/PortDescription.java b/net/api/src/main/java/net/onrc/onos/api/device/PortDescription.java
deleted file mode 100644
index 9f5db2a..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/device/PortDescription.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api.device;
-
-/**
- * Information about a port.
- */
-public interface PortDescription {
-
- // TODO: possibly relocate this to a common ground so that this can also used by host tracking if required
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/flow/FlowDescription.java b/net/api/src/main/java/net/onrc/onos/api/flow/FlowDescription.java
deleted file mode 100644
index 80fc051..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/flow/FlowDescription.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package net.onrc.onos.api.flow;
-
-package net.onrc.onos.api.Description;
-
-/**
- * Information about a flow rule.
- */
-public interface FlowDescription extends Description {
-
- // Match and action, possibly reason for flow rule, unless reason is too OF-specific.
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProvider.java b/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProvider.java
deleted file mode 100644
index acb63b4..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProvider.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package net.onrc.onos.api.flow;
-
-import net.onrc.onos.api.Provider;
-
-/**
- * Abstraction of a flow rule provider.
- */
-public interface FlowRuleProvider extends Provider {
-}
\ No newline at end of file
diff --git a/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProviderBroker.java b/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProviderBroker.java
deleted file mode 100644
index 27f1ca6..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProviderBroker.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api.flow;
-
-import net.onrc.onos.api.ProviderBroker;
-
-/**
- * Abstraction for a flow rule provider brokerage.
- */
-public interface FlowRuleProviderBroker
- extends ProviderBroker<FlowRuleProvider, FlowRuleProviderService> {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProviderService.java b/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProviderService.java
deleted file mode 100644
index 8f90c32..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/flow/FlowRuleProviderService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.onrc.onos.api.flow;
-
-import net.onrc.onos.api.ProviderService;
-
-/**
- * Service through which flowrule providers can inject flowrule information into
- * the core.
- */
-public interface FlowRuleProviderService extends ProviderService {
-
- /**
- * Signals that a flow that was previously installed has been removed.
- *
- * @param flowDescription information about the removed flow
- */
- void flowRemoved(FlowDescription flowDescription);
-
- /**
- * Signals that a flowrule is missing for some network traffic.
- *
- * @param flowDescription information about traffic in need of flow rule(s)
- */
- void flowMissing(FlowDescription flowDescription);
-
- /**
- * Signals that a flowrule has been added.
- *
- * TODO think about if this really makes sense, e.g. if stats collection or
- * something can leverage it.
- *
- * @param flowDescription the rule that was added
- */
- void flowAdded(FlowDescription flowDescription);
-
-}
\ No newline at end of file
diff --git a/net/api/src/main/java/net/onrc/onos/api/host/HostDescription.java b/net/api/src/main/java/net/onrc/onos/api/host/HostDescription.java
deleted file mode 100644
index a397155..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/host/HostDescription.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package net.onrc.onos.api.host;
-
-/**
- * Information describing host and its location.
- */
-public interface HostDescription {
-
- // IP, MAC, VLAN-ID, HostLocation -> (ConnectionPoint + timestamp)
-
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/host/HostProvider.java b/net/api/src/main/java/net/onrc/onos/api/host/HostProvider.java
deleted file mode 100644
index f05e26d..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/host/HostProvider.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package net.onrc.onos.api.host;
-
-import net.onrc.onos.api.Provider;
-
-/**
- * Provider of information about hosts and their location on the network.
- */
-public interface HostProvider extends Provider {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/host/HostProviderBroker.java b/net/api/src/main/java/net/onrc/onos/api/host/HostProviderBroker.java
deleted file mode 100644
index c799b20..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/host/HostProviderBroker.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api.host;
-
-import net.onrc.onos.api.ProviderBroker;
-
-/**
- * Abstraction of a host provider brokerage.
- */
-public interface HostProviderBroker
- extends ProviderBroker<HostProvider, HostProviderService> {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/host/HostProviderService.java b/net/api/src/main/java/net/onrc/onos/api/host/HostProviderService.java
deleted file mode 100644
index 662ba75..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/host/HostProviderService.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package net.onrc.onos.api.host;
-
-import net.onrc.onos.api.ProviderService;
-
-/**
- * Means of conveying host information to the core.
- */
-public interface HostProviderService extends ProviderService {
-
- void hostDetected(HostDescription hostDescription);
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/link/LinkDescription.java b/net/api/src/main/java/net/onrc/onos/api/link/LinkDescription.java
deleted file mode 100644
index c40f522..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/link/LinkDescription.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package net.onrc.onos.api.link;
-
-/**
- * Describes an infrastructure link.
- */
-public interface LinkDescription {
-
- // TODO: src, dst connection points, which are pairs of (DeviceId, PortNumber)
-
-// On the north:
-// Link = (ConnectPoint src, ConnectPoint dst);
-// ConnectPoint = (DeviceId, PortNumber);
-
-// On the south
-// LinkDescription ~ Link
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/link/LinkProvider.java b/net/api/src/main/java/net/onrc/onos/api/link/LinkProvider.java
deleted file mode 100644
index 4d7ab86..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/link/LinkProvider.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api.link;
-
-import net.onrc.onos.api.Provider;
-
-/**
- * Abstraction of an entity providing information about infrastructure links
- * to the core.
- */
-public interface LinkProvider extends Provider {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/link/LinkProviderBroker.java b/net/api/src/main/java/net/onrc/onos/api/link/LinkProviderBroker.java
deleted file mode 100644
index 8da7bab..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/link/LinkProviderBroker.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api.link;
-
-import net.onrc.onos.api.ProviderBroker;
-
-/**
- * Abstraction of an infrastructure link provider brokerage.
- */
-public interface LinkProviderBroker
- extends ProviderBroker<LinkProvider, LinkProviderService> {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/link/LinkProviderService.java b/net/api/src/main/java/net/onrc/onos/api/link/LinkProviderService.java
deleted file mode 100644
index 23fced8..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/link/LinkProviderService.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package net.onrc.onos.api.link;
-
-import net.onrc.onos.api.ProviderService;
-
-/**
- * Means for injecting link information into the core.
- */
-public interface LinkProviderService extends ProviderService {
-
- /**
- * Signals that an infrastructure link has been connected.
- *
- * @param linkDescription link information
- */
- void linkConnected(LinkDescription linkDescription);
-
- /**
- * Signals that an infrastructure link has been disconnected.
- *
- * @param linkDescription link information
- */
- void linkDisconnected(LinkDescription linkDescription);
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/topology/TopologyDescription.java b/net/api/src/main/java/net/onrc/onos/api/topology/TopologyDescription.java
deleted file mode 100644
index 306447e..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/topology/TopologyDescription.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package net.onrc.onos.api.topology;
-
-import net.onrc.onos.api.Description;
-
-import java.util.Collection;
-
-/**
- * Describes attribute(s) of a network topology.
- */
-public interface TopologyDescription extends Description {
-
- /**
- * A collection of Device, Link, and Host descriptors that describe
- * the changes tha have occurred in the network topology.
- *
- * @return network element descriptions describing topology change
- */
- Collection<Description> details();
-
-}
\ No newline at end of file
diff --git a/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProvider.java b/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProvider.java
deleted file mode 100644
index f997c61..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProvider.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api.topology;
-
-import net.onrc.onos.api.Provider;
-
-/**
- * Means for injecting topology information into the core.
- */
-public interface TopologyProvider extends Provider {
-
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProviderBroker.java b/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProviderBroker.java
deleted file mode 100644
index 207f33a..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProviderBroker.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package net.onrc.onos.api.topology;
-
-import net.onrc.onos.api.ProviderBroker;
-
-/**
- * Abstraction of a network topology provider brokerage.
- */
-public interface TopologyProviderBroker extends
- ProviderBroker<TopologyProvider, TopologyProviderService> {
-}
diff --git a/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProviderService.java b/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProviderService.java
deleted file mode 100644
index 67fbb1d..0000000
--- a/net/api/src/main/java/net/onrc/onos/api/topology/TopologyProviderService.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package net.onrc.onos.api.topology;
-
-import net.onrc.onos.api.ProviderService;
-
-/**
- * Means for injecting topology information into the core.
- */
-public interface TopologyProviderService extends ProviderService {
-
- // What can be conveyed in a topology that isn't by individual
- // providers?
-
- /**
- * Signals the core that some aspect of the topology has changed.
- *
- * @param topoDescription information about topology
- */
- void topologyChanged(TopologyDescription topoDescription);
-
-}
diff --git a/net/api/src/main/java/org/onlab/onos/net/Description.java b/net/api/src/main/java/org/onlab/onos/net/Description.java
new file mode 100644
index 0000000..38338c1
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/Description.java
@@ -0,0 +1,7 @@
+package org.onlab.onos.net;
+
+/**
+ * Base abstraction of a piece of information about network elements.
+ */
+public interface Description {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/DeviceId.java b/net/api/src/main/java/org/onlab/onos/net/DeviceId.java
new file mode 100644
index 0000000..ebb3fb7
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/DeviceId.java
@@ -0,0 +1,25 @@
+package org.onlab.onos.net;
+
+import java.net.URI;
+
+/**
+ * Immutable representaion of a device identity.
+ */
+public class DeviceId {
+
+ private final URI uri;
+
+ public DeviceId(URI uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Returns the backing URI.
+ *
+ * @return backing device URI
+ */
+ public URI uri() {
+ return uri;
+ }
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/GreetService.java b/net/api/src/main/java/org/onlab/onos/net/GreetService.java
new file mode 100644
index 0000000..09f0d96
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/GreetService.java
@@ -0,0 +1,23 @@
+package org.onlab.onos.net;
+
+/**
+ * Example of a simple service that provides greetings and it
+ * remembers the names which were greeted.
+ */
+public interface GreetService {
+
+ /**
+ * Returns a greeting tailored to the specified name.
+ *
+ * @param name some name
+ * @return greeting
+ */
+ String yo(String name);
+
+ /**
+ * Returns an iterable of names encountered thus far.
+ *
+ * @return iterable of names
+ */
+ Iterable<String> names();
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/PortNumber.java b/net/api/src/main/java/org/onlab/onos/net/PortNumber.java
new file mode 100644
index 0000000..4ea4e24
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/PortNumber.java
@@ -0,0 +1,7 @@
+package org.onlab.onos.net;
+
+/**
+ * Representation of a port number.
+ */
+public interface PortNumber {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/Provider.java b/net/api/src/main/java/org/onlab/onos/net/Provider.java
new file mode 100644
index 0000000..eda436b
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/Provider.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net;
+
+/**
+ * Abstraction of a provider of information about network environment.
+ */
+public interface Provider {
+
+ ProviderId id();
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/ProviderBroker.java b/net/api/src/main/java/org/onlab/onos/net/ProviderBroker.java
new file mode 100644
index 0000000..63d7189
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/ProviderBroker.java
@@ -0,0 +1,27 @@
+package org.onlab.onos.net;
+
+/**
+ * Broker used for registering/unregistering information providers with the core.
+ *
+ * @param <T> type of the information provider
+ * @param <S> type of the provider service
+ */
+public interface ProviderBroker<T extends Provider, S extends ProviderService> {
+
+ /**
+ * Registers the supplied provider with the core.
+ *
+ * @param provider provider to be registered
+ * @return provider service for injecting information into core
+ */
+ S register(T provider);
+
+ /**
+ * Unregisters the supplied provider. As a result the previously issued
+ * provider service will be invalidated.
+ *
+ * @param provider provider to be unregistered
+ */
+ void unregister(T provider);
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/ProviderId.java b/net/api/src/main/java/org/onlab/onos/net/ProviderId.java
new file mode 100644
index 0000000..53dd739
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/ProviderId.java
@@ -0,0 +1,43 @@
+package org.onlab.onos.net;
+
+/**
+ * Notion of provider identity.
+ */
+public class ProviderId {
+
+ private final String id;
+
+ public ProviderId(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ProviderId that = (ProviderId) o;
+
+ if (!id.equals(that.id)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "ProviderId{" +
+ "id='" + id + '\'' +
+ '}';
+ }
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/ProviderService.java b/net/api/src/main/java/org/onlab/onos/net/ProviderService.java
new file mode 100644
index 0000000..8a7d7e9
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/ProviderService.java
@@ -0,0 +1,8 @@
+package org.onlab.onos.net;
+
+/**
+ * Abstraction of a service through which providers can inject information
+ * about the network environment into the core.
+ */
+public interface ProviderService {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/device/DeviceDescription.java b/net/api/src/main/java/org/onlab/onos/net/device/DeviceDescription.java
new file mode 100644
index 0000000..2b83890
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/device/DeviceDescription.java
@@ -0,0 +1,21 @@
+package org.onlab.onos.net.device;
+
+import org.onlab.onos.net.Description;
+
+import java.net.URI;
+
+/**
+ * Carrier of immutable information about a device.
+ */
+public interface DeviceDescription extends Description {
+
+ /**
+ * Protocol/provider specific URI that can be used to encode the identity
+ * information required to communicate with the device externally, e.g.
+ * datapath ID.
+ *
+ * @return provider specific URI for the device
+ */
+ URI deviceURI();
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java b/net/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java
new file mode 100644
index 0000000..04ca92c
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java
@@ -0,0 +1,9 @@
+package org.onlab.onos.net.device;
+
+import org.onlab.onos.net.Provider;
+
+/**
+ * Abstraction of a device information provider.
+ */
+public interface DeviceProvider extends Provider {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderBroker.java b/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderBroker.java
new file mode 100644
index 0000000..926f76e
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderBroker.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net.device;
+
+import org.onlab.onos.net.ProviderBroker;
+
+/**
+ * Abstraction of a device provider brokerage.
+ */
+public interface DeviceProviderBroker
+ extends ProviderBroker<DeviceProvider, DeviceProviderService> {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java b/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java
new file mode 100644
index 0000000..e5ee1f0
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java
@@ -0,0 +1,44 @@
+package org.onlab.onos.net.device;
+
+import org.onlab.onos.net.ProviderService;
+
+import java.util.List;
+
+/**
+ * Service through which device providers can inject device information into
+ * the core.
+ */
+public interface DeviceProviderService extends ProviderService {
+
+ // TODO: define suspend and remove actions on the mezzanine administrative API
+
+ /**
+ * Signals the core that a device has connected or has been detected somehow.
+ *
+ * @param deviceDescription information about network device
+ */
+ void deviceConnected(DeviceDescription deviceDescription);
+
+ /**
+ * Signals the core that a device has disconnected or is no longer reachable.
+ *
+ * @param deviceDescription device to be removed
+ */
+ void deviceDisconnected(DeviceDescription deviceDescription);
+
+ /**
+ * Sends information about all ports of a device. It is up to the core to
+ * determine what has changed.
+ *
+ * @param ports list of device ports
+ */
+ void updatePorts(List<PortDescription> ports);
+
+ /**
+ * Used to notify the core about port status change of a single port.
+ *
+ * @param port description of the port that changed
+ */
+ void portStatusChanged(PortDescription port);
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/device/PortDescription.java b/net/api/src/main/java/org/onlab/onos/net/device/PortDescription.java
new file mode 100644
index 0000000..4c944ab
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/device/PortDescription.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net.device;
+
+/**
+ * Information about a port.
+ */
+public interface PortDescription {
+
+ // TODO: possibly relocate this to a common ground so that this can also used by host tracking if required
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/flow/FlowDescription.java b/net/api/src/main/java/org/onlab/onos/net/flow/FlowDescription.java
new file mode 100644
index 0000000..2a64815
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/flow/FlowDescription.java
@@ -0,0 +1,12 @@
+package org.onlab.onos.net.flow;
+
+import org.onlab.onos.net.Description;
+
+/**
+ * Information about a flow rule.
+ */
+public interface FlowDescription extends Description {
+
+ // Match and action, possibly reason for flow rule, unless reason is too OF-specific.
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProvider.java b/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProvider.java
new file mode 100644
index 0000000..ac46da8
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProvider.java
@@ -0,0 +1,9 @@
+package org.onlab.onos.net.flow;
+
+import org.onlab.onos.net.Provider;
+
+/**
+ * Abstraction of a flow rule provider.
+ */
+public interface FlowRuleProvider extends Provider {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderBroker.java b/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderBroker.java
new file mode 100644
index 0000000..c3f7602
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderBroker.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net.flow;
+
+import org.onlab.onos.net.ProviderBroker;
+
+/**
+ * Abstraction for a flow rule provider brokerage.
+ */
+public interface FlowRuleProviderBroker
+ extends ProviderBroker<FlowRuleProvider, FlowRuleProviderService> {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java b/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java
new file mode 100644
index 0000000..9b26d76
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/flow/FlowRuleProviderService.java
@@ -0,0 +1,35 @@
+package org.onlab.onos.net.flow;
+
+import org.onlab.onos.net.ProviderService;
+
+/**
+ * Service through which flowrule providers can inject flowrule information into
+ * the core.
+ */
+public interface FlowRuleProviderService extends ProviderService {
+
+ /**
+ * Signals that a flow that was previously installed has been removed.
+ *
+ * @param flowDescription information about the removed flow
+ */
+ void flowRemoved(FlowDescription flowDescription);
+
+ /**
+ * Signals that a flowrule is missing for some network traffic.
+ *
+ * @param flowDescription information about traffic in need of flow rule(s)
+ */
+ void flowMissing(FlowDescription flowDescription);
+
+ /**
+ * Signals that a flowrule has been added.
+ *
+ * TODO think about if this really makes sense, e.g. if stats collection or
+ * something can leverage it.
+ *
+ * @param flowDescription the rule that was added
+ */
+ void flowAdded(FlowDescription flowDescription);
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/host/HostDescription.java b/net/api/src/main/java/org/onlab/onos/net/host/HostDescription.java
new file mode 100644
index 0000000..e3c67b9
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/host/HostDescription.java
@@ -0,0 +1,11 @@
+package org.onlab.onos.net.host;
+
+/**
+ * Information describing host and its location.
+ */
+public interface HostDescription {
+
+ // IP, MAC, VLAN-ID, HostLocation -> (ConnectionPoint + timestamp)
+
+}
+
diff --git a/net/api/src/main/java/org/onlab/onos/net/host/HostProvider.java b/net/api/src/main/java/org/onlab/onos/net/host/HostProvider.java
new file mode 100644
index 0000000..1ad2c65
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/host/HostProvider.java
@@ -0,0 +1,9 @@
+package org.onlab.onos.net.host;
+
+import org.onlab.onos.net.Provider;
+
+/**
+ * Provider of information about hosts and their location on the network.
+ */
+public interface HostProvider extends Provider {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/host/HostProviderBroker.java b/net/api/src/main/java/org/onlab/onos/net/host/HostProviderBroker.java
new file mode 100644
index 0000000..427e54e
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/host/HostProviderBroker.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net.host;
+
+import org.onlab.onos.net.ProviderBroker;
+
+/**
+ * Abstraction of a host provider brokerage.
+ */
+public interface HostProviderBroker
+ extends ProviderBroker<HostProvider, HostProviderService> {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/host/HostProviderService.java b/net/api/src/main/java/org/onlab/onos/net/host/HostProviderService.java
new file mode 100644
index 0000000..4d5d470
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/host/HostProviderService.java
@@ -0,0 +1,12 @@
+package org.onlab.onos.net.host;
+
+import org.onlab.onos.net.ProviderService;
+
+/**
+ * Means of conveying host information to the core.
+ */
+public interface HostProviderService extends ProviderService {
+
+ void hostDetected(HostDescription hostDescription);
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/link/LinkDescription.java b/net/api/src/main/java/org/onlab/onos/net/link/LinkDescription.java
new file mode 100644
index 0000000..8d712f0
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/link/LinkDescription.java
@@ -0,0 +1,17 @@
+package org.onlab.onos.net.link;
+
+/**
+ * Describes an infrastructure link.
+ */
+public interface LinkDescription {
+
+ // TODO: src, dst connection points, which are pairs of (DeviceId, PortNumber)
+
+// On the north:
+// Link = (ConnectPoint src, ConnectPoint dst);
+// ConnectPoint = (DeviceId, PortNumber);
+
+// On the south
+// LinkDescription ~ Link
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/link/LinkProvider.java b/net/api/src/main/java/org/onlab/onos/net/link/LinkProvider.java
new file mode 100644
index 0000000..57cc45d
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/link/LinkProvider.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net.link;
+
+import org.onlab.onos.net.Provider;
+
+/**
+ * Abstraction of an entity providing information about infrastructure links
+ * to the core.
+ */
+public interface LinkProvider extends Provider {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderBroker.java b/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderBroker.java
new file mode 100644
index 0000000..b0bfb05
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderBroker.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net.link;
+
+import org.onlab.onos.net.ProviderBroker;
+
+/**
+ * Abstraction of an infrastructure link provider brokerage.
+ */
+public interface LinkProviderBroker
+ extends ProviderBroker<LinkProvider, LinkProviderService> {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderService.java b/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderService.java
new file mode 100644
index 0000000..9f523f7
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/link/LinkProviderService.java
@@ -0,0 +1,24 @@
+package org.onlab.onos.net.link;
+
+import org.onlab.onos.net.ProviderService;
+
+/**
+ * Means for injecting link information into the core.
+ */
+public interface LinkProviderService extends ProviderService {
+
+ /**
+ * Signals that an infrastructure link has been connected.
+ *
+ * @param linkDescription link information
+ */
+ void linkConnected(LinkDescription linkDescription);
+
+ /**
+ * Signals that an infrastructure link has been disconnected.
+ *
+ * @param linkDescription link information
+ */
+ void linkDisconnected(LinkDescription linkDescription);
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyDescription.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyDescription.java
new file mode 100644
index 0000000..0c55314
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyDescription.java
@@ -0,0 +1,20 @@
+package org.onlab.onos.net.topology;
+
+import org.onlab.onos.net.Description;
+
+import java.util.Collection;
+
+/**
+ * Describes attribute(s) of a network topology.
+ */
+public interface TopologyDescription extends Description {
+
+ /**
+ * A collection of Device, Link, and Host descriptors that describe
+ * the changes tha have occurred in the network topology.
+ *
+ * @return network element descriptions describing topology change
+ */
+ Collection<Description> details();
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProvider.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProvider.java
new file mode 100644
index 0000000..70264dc
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProvider.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net.topology;
+
+import org.onlab.onos.net.Provider;
+
+/**
+ * Means for injecting topology information into the core.
+ */
+public interface TopologyProvider extends Provider {
+
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderBroker.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderBroker.java
new file mode 100644
index 0000000..9caa817
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderBroker.java
@@ -0,0 +1,10 @@
+package org.onlab.onos.net.topology;
+
+import org.onlab.onos.net.ProviderBroker;
+
+/**
+ * Abstraction of a network topology provider brokerage.
+ */
+public interface TopologyProviderBroker extends
+ ProviderBroker<TopologyProvider, TopologyProviderService> {
+}
diff --git a/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java
new file mode 100644
index 0000000..bef83ed
--- /dev/null
+++ b/net/api/src/main/java/org/onlab/onos/net/topology/TopologyProviderService.java
@@ -0,0 +1,20 @@
+package org.onlab.onos.net.topology;
+
+import org.onlab.onos.net.ProviderService;
+
+/**
+ * Means for injecting topology information into the core.
+ */
+public interface TopologyProviderService extends ProviderService {
+
+ // What can be conveyed in a topology that isn't by individual
+ // providers?
+
+ /**
+ * Signals the core that some aspect of the topology has changed.
+ *
+ * @param topoDescription information about topology
+ */
+ void topologyChanged(TopologyDescription topoDescription);
+
+}
diff --git a/net/api/src/main/javadoc/org/onlab/onos/net/package.html b/net/api/src/main/javadoc/org/onlab/onos/net/package.html
new file mode 100644
index 0000000..f03b788
--- /dev/null
+++ b/net/api/src/main/javadoc/org/onlab/onos/net/package.html
@@ -0,0 +1,3 @@
+<body>
+ONOS API definitions.
+</body>
\ No newline at end of file
diff --git a/net/core/pom.xml b/net/core/pom.xml
new file mode 100644
index 0000000..30f6e12
--- /dev/null
+++ b/net/core/pom.xml
@@ -0,0 +1,43 @@
+<?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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onos-net</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-core</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>ONOS network control core subsystems</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onos-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/net/core/src/main/java/org/onlab/onos/net/impl/GreetManager.java b/net/core/src/main/java/org/onlab/onos/net/impl/GreetManager.java
new file mode 100644
index 0000000..65a42bc
--- /dev/null
+++ b/net/core/src/main/java/org/onlab/onos/net/impl/GreetManager.java
@@ -0,0 +1,52 @@
+package org.onlab.onos.net.impl;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.net.GreetService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Trivial implementation of the seed service to demonstrate component and
+ * service annotations.
+ */
+@Component(immediate = true)
+@Service
+public class GreetManager implements GreetService {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final Set<String> names = new HashSet<>();
+
+ @Override
+ public synchronized String yo(String name) {
+ checkNotNull(name, "Name cannot be null");
+ names.add(name);
+ log.info("Greeted '{}'", name);
+ return "Whazup " + name + "?";
+ }
+
+ @Override
+ public synchronized Iterable<String> names() {
+ return ImmutableSet.copyOf(names);
+ }
+
+ @Activate
+ public void activate() {
+ log.info("SeedManager started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("SeedManager stopped");
+ }
+
+}
diff --git a/net/core/src/main/java/org/onlab/onos/net/impl/SomeOtherComponent.java b/net/core/src/main/java/org/onlab/onos/net/impl/SomeOtherComponent.java
new file mode 100644
index 0000000..c53ab04
--- /dev/null
+++ b/net/core/src/main/java/org/onlab/onos/net/impl/SomeOtherComponent.java
@@ -0,0 +1,36 @@
+package org.onlab.onos.net.impl;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.net.GreetService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Example of a component that does not provide any service, but consumes one.
+ */
+@Component(immediate = true)
+public class SomeOtherComponent {
+
+ private final Logger log = LoggerFactory.getLogger(SomeOtherComponent.class);
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected GreetService service;
+ // protected to allow injection for testing;
+ // alternative is to write bindSeedService and unbindSeedService, which is more code
+
+ @Activate
+ public void activate() {
+ log.info("SomeOtherComponent started");
+ service.yo("neighbour");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("SomeOtherComponent stopped");
+ }
+
+}
diff --git a/net/core/src/main/javadoc/org/onlab/onos/net/impl/package.html b/net/core/src/main/javadoc/org/onlab/onos/net/impl/package.html
new file mode 100644
index 0000000..ba285bd
--- /dev/null
+++ b/net/core/src/main/javadoc/org/onlab/onos/net/impl/package.html
@@ -0,0 +1,3 @@
+<body>
+ONOS core implementations.
+</body>
\ No newline at end of file
diff --git a/net/core/src/test/java/org/onlab/onos/net/impl/GreetManagerTest.java b/net/core/src/test/java/org/onlab/onos/net/impl/GreetManagerTest.java
new file mode 100644
index 0000000..9c05f20
--- /dev/null
+++ b/net/core/src/test/java/org/onlab/onos/net/impl/GreetManagerTest.java
@@ -0,0 +1,31 @@
+package org.onlab.onos.net.impl;
+
+import org.junit.Test;
+import org.onlab.onos.net.GreetService;
+
+import java.util.Iterator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * Example of a component & service implementation unit test.
+ */
+public class GreetManagerTest {
+
+ @Test
+ public void basics() {
+ GreetService service = new GreetManager();
+ assertEquals("incorrect greeting", "Whazup dude?", service.yo("dude"));
+
+ Iterator<String> names = service.names().iterator();
+ assertEquals("incorrect name", "dude", names.next());
+ assertFalse("no more names expected", names.hasNext());
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void nullArg() {
+ new GreetManager().yo(null);
+ }
+
+}
diff --git a/net/pom.xml b/net/pom.xml
new file mode 100644
index 0000000..bd4fa6e
--- /dev/null
+++ b/net/pom.xml
@@ -0,0 +1,40 @@
+<?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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onos</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-net</artifactId>
+ <packaging>pom</packaging>
+
+ <description>ONOS Core root project</description>
+
+ <modules>
+ <module>api</module>
+ <module>core</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/of-save/ctl/conf/checkstyle/checkstyle_maven.properties b/of-save/ctl/conf/checkstyle/checkstyle_maven.properties
new file mode 100644
index 0000000..4677e08
--- /dev/null
+++ b/of-save/ctl/conf/checkstyle/checkstyle_maven.properties
@@ -0,0 +1,2 @@
+# See: http://rolf-engelhard.de/2011/04/using-the-same-suppression-filter-for-checkstyle-in-eclipse-and-maven/
+config_loc=conf/checkstyle
diff --git a/of-save/ctl/conf/checkstyle/sun_checks.xml b/of-save/ctl/conf/checkstyle/sun_checks.xml
new file mode 100644
index 0000000..b1404c1
--- /dev/null
+++ b/of-save/ctl/conf/checkstyle/sun_checks.xml
@@ -0,0 +1,284 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+
+<!--
+
+ Checkstyle configuration that checks the sun coding conventions from:
+
+ - the Java Language Specification at
+ http://java.sun.com/docs/books/jls/second_edition/html/index.html
+
+ - the Sun Code Conventions at http://java.sun.com/docs/codeconv/
+
+ - the Javadoc guidelines at
+ http://java.sun.com/j2se/javadoc/writingdoccomments/index.html
+
+ - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html
+
+ - some best practices
+
+ Checkstyle is very configurable. Be sure to read the documentation at
+ http://checkstyle.sf.net (or in your downloaded distribution).
+
+ Most Checks are configurable, be sure to consult the documentation.
+
+ To completely disable a check, just comment it out or delete it from the file.
+
+ Finally, it is worth reading the documentation.
+
+-->
+
+
+<!--
+ The default severity setting in checkstyle is 'error', so some
+ of the rules below are configured to change the severity to
+ 'warning'. Over time, these 'warning' settings should be
+ removed as more of the ONOS source code is modified to
+ follow the recommended rules.
+-->
+
+
+
+<module name="Checker">
+ <module name="SuppressionFilter">
+ <property name="file" value="${config_loc}/suppressions.xml"/>
+ </module>
+ <!--
+ If you set the basedir property below, then all reported file
+ names will be relative to the specified directory. See
+ http://checkstyle.sourceforge.net/5.x/config.html#Checker
+
+ <property name="basedir" value="${basedir}"/>
+ -->
+ <!-- Checks that a package-info.java file exists for each package. -->
+ <!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
+ <!-- ONOS does not currently supply package level Javadoc information
+ in package-info files -->
+ <!-- <module name="JavadocPackage"/> -->
+
+ <!-- Checks whether files end with a new line. -->
+ <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
+ <module name="NewlineAtEndOfFile"/>
+
+ <!-- Checks that property files contain the same keys. -->
+ <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
+ <module name="Translation"/>
+
+ <!-- Checks for Size Violations. -->
+ <!-- See http://checkstyle.sf.net/config_sizes.html -->
+ <module name="FileLength">
+ <property name="max" value="2500"/>
+ </module>
+
+ <!-- Checks for whitespace -->
+ <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+ <module name="FileTabCharacter"/>
+
+ <!-- Miscellaneous other checks. -->
+ <!-- See http://checkstyle.sf.net/config_misc.html -->
+ <module name="RegexpSingleline">
+ <property name="format" value="\s+$"/>
+ <property name="minimum" value="0"/>
+ <property name="maximum" value="0"/>
+ <property name="message" value="Line has trailing spaces."/>
+ </module>
+
+ <!-- Checks for Headers -->
+ <!-- See http://checkstyle.sf.net/config_header.html -->
+ <!-- <module name="Header"> -->
+ <!-- <property name="headerFile" value="${checkstyle.header.file}"/> -->
+ <!-- <property name="fileExtensions" value="java"/> -->
+ <!-- </module> -->
+
+ <module name="SuppressionCommentFilter">
+ <property name="offCommentFormat" value="(CHECKSTYLE\:OFF|Generated by the protocol buffer compiler.)"/>
+ <property name="onCommentFormat" value="CHECKSTYLE:ON"/>
+ </module>
+
+ <module name="SuppressWithNearbyCommentFilter">
+ <property name="commentFormat" value="CHECKSTYLE IGNORE THIS LINE" />
+ <property name="checkFormat" value=".*" />
+ <property name="influenceFormat" value="0" />
+ </module>
+
+ <!-- Example: // CHECKSTYLE IGNORE FinalClass FOR NEXT 1 LINES -->
+ <module name="SuppressWithNearbyCommentFilter">
+ <property name="commentFormat" value="CHECKSTYLE IGNORE (\w+) FOR NEXT (\d+) LINES"/>
+ <property name="checkFormat" value="$1"/>
+ <property name="influenceFormat" value="$2"/>
+ </module>
+
+ <module name="TreeWalker">
+
+ <module name="FileContentsHolder"/>
+ <!-- Checks for Javadoc comments. -->
+ <!-- See http://checkstyle.sf.net/config_javadoc.html -->
+ <module name="JavadocMethod">
+ <property name="severity" value="warning"/>
+ <property name="allowUndeclaredRTE" value="true"/>
+ </module>
+ <module name="JavadocType">
+ <property name="severity" value="warning"/>
+ </module>
+ <module name="JavadocVariable">
+ <!-- Suppress check for private member Javadocs.
+ Possibly revist fixing these. -->
+ <property name="scope" value="public"/>
+ <property name="severity" value="warning"/>
+ </module>
+ <module name="JavadocStyle"/>
+ <!-- @author tag should not be used -->
+ <module name="WriteTag">
+ <property name="tag" value="@author"/>
+ <property name="tagFormat" value="\S"/>
+ <property name="severity" value="ignore"/>
+ <property name="tagSeverity" value="error"/>
+ </module>
+
+
+ <!-- Checks for Naming Conventions. -->
+ <!-- See http://checkstyle.sf.net/config_naming.html -->
+ <module name="ConstantName">
+ <!-- ONOS allows the name "log" for static final Loggers -->
+ <property name="format"
+ value="^log$|^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"/>
+ </module>
+ <module name="LocalFinalVariableName"/>
+
+ <module name="LocalVariableName"/>
+
+ <module name="MemberName"/>
+ <module name="MethodName"/>
+ <module name="PackageName"/>
+ <module name="ParameterName"/>
+ <module name="StaticVariableName"/>
+ <module name="TypeName"/>
+
+ <!-- Checks for imports -->
+ <!-- See http://checkstyle.sf.net/config_import.html -->
+ <module name="AvoidStarImport">
+ <property name="allowStaticMemberImports" value="true"/>
+ </module>
+ <module name="IllegalImport"/>
+ <!-- defaults to sun.* packages -->
+ <module name="RedundantImport"/>
+ <module name="UnusedImports"/>
+
+
+ <!-- Checks for Size Violations. -->
+ <!-- See http://checkstyle.sf.net/config_sizes.html -->
+ <module name="LineLength">
+ <!-- ONOS standard usage is 80 columns, but we allow up
+ to 120 to not break the build. -->
+ <property name="max" value="120"/>
+ <property name="ignorePattern" value="^import"/>
+ </module>
+ <module name="MethodLength">
+ <property name="max" value="400"/>
+ </module>
+
+ <module name="ParameterNumber"/>
+
+ <!-- Checks for whitespace -->
+ <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+ <module name="EmptyForIteratorPad"/>
+ <module name="GenericWhitespace"/>
+ <module name="MethodParamPad"/>
+ <module name="NoWhitespaceAfter"/>
+ <module name="NoWhitespaceBefore"/>
+
+ <!-- Disabled for ONOS. Default rules specify undesired behavior for the '?' operator -->
+ <!-- <module name="OperatorWrap"/> -->
+ <module name="ParenPad"/>
+ <module name="TypecastParenPad"/>
+ <module name="WhitespaceAfter"/>
+ <module name="WhitespaceAround">
+ <property name="allowEmptyConstructors" value="true"/>
+ <property name="allowEmptyMethods" value="true"/>
+ </module>
+
+
+
+ <!-- Modifier Checks -->
+ <!-- See http://checkstyle.sf.net/config_modifiers.html -->
+ <module name="ModifierOrder"/>
+
+ <!-- Disabled for ONOS to allow use of public -->
+ <!-- modifiers in interfaces. -->
+ <!-- <module name="RedundantModifier"/> -->
+
+
+ <!-- Checks for blocks. You know, those {}'s -->
+ <!-- See http://checkstyle.sf.net/config_blocks.html -->
+ <module name="AvoidNestedBlocks">
+ <!-- ONOS alows declarations inside of switch case blocks -->
+ <property name="allowInSwitchCase" value="true"/>
+ </module>
+ <module name="EmptyBlock"/>
+ <module name="LeftCurly"/>
+ <module name="NeedBraces"/>
+ <module name="RightCurly"/>
+
+ <!-- Checks for common coding problems -->
+ <!-- See http://checkstyle.sf.net/config_coding.html -->
+ <!-- ONOS allows conditional operators -->
+ <!-- <module name="AvoidInlineConditionals"/> -->
+ <module name="EmptyStatement"/>
+ <module name="EqualsHashCode"/>
+
+ <module name="HiddenField">
+ <property name="ignoreSetter" value="true"/>
+ <property name="ignoreConstructorParameter" value="true"/>
+ </module>
+
+ <module name="IllegalInstantiation"/>
+ <module name="InnerAssignment"/>
+
+ <!-- Many violations of this rule present, revist in a
+ subsequent round of cleanups -->
+ <!-- <module name="MagicNumber"/> -->
+ <module name="MissingSwitchDefault"/>
+
+ <module name="RedundantThrows">
+ <property name="allowSubclasses" value="true"/>
+ <property name="allowUnchecked" value="true"/>
+ <property name="suppressLoadErrors" value="true"/>
+ </module>
+
+ <module name="SimplifyBooleanExpression"/>
+ <module name="SimplifyBooleanReturn"/>
+
+ <!-- Checks for class design -->
+ <!-- See http://checkstyle.sf.net/config_design.html -->
+ <!-- ONOS produces many warnings of this type.
+ Fixing all of these is outside the scope of the current cleanup. -->
+ <!-- <module name="DesignForExtension"/> -->
+ <module name="FinalClass"/>
+
+ <module name="HideUtilityClassConstructor"/>
+
+ <module name="InterfaceIsType"/>
+
+ <module name="VisibilityModifier">
+ <property name="severity" value="warning"/>
+ </module>
+
+
+
+ <!-- Miscellaneous other checks. -->
+ <!-- See http://checkstyle.sf.net/config_misc.html -->
+ <module name="ArrayTypeStyle"/>
+
+ <!-- Many violations of this rule currently, too many to fix
+ in the current cleanup. -->
+ <!-- <module name="FinalParameters"/> -->
+ <!-- ONOS allows TODO markers in checked in source code -->
+ <!-- <module name="TodoComment"/> -->
+ <module name="UpperEll"/>
+
+ </module>
+
+ </module>
diff --git a/of-save/ctl/conf/checkstyle/suppressions.xml b/of-save/ctl/conf/checkstyle/suppressions.xml
new file mode 100644
index 0000000..41dbe2d
--- /dev/null
+++ b/of-save/ctl/conf/checkstyle/suppressions.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN" "http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
+
+<suppressions>
+ <!--
+ Note: Exclusion definition exists in multiple places.
+ - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
+ - In file conf/checkstyle/onos_suppressions.xml (this file)
+ - maven-pmd-plugin configuration in pom.xml
+ (under build and reporting)
+ -->
+
+ <suppress files=".*" checks="FinalParametersCheck"/>
+ <suppress files=".*" checks="MagicNumbersCheck"/>
+ <suppress files=".*" checks="DesignForExtensionCheck"/>
+ <suppress files=".*" checks="TodoCommentCheck"/>
+ <suppress files=".*" checks="AvoidInlineConditionalsCheck"/>
+ <suppress files=".*" checks="OperatorWrapCheck"/>
+</suppressions>
+
diff --git a/of-save/ctl/conf/findbugs/exclude.xml b/of-save/ctl/conf/findbugs/exclude.xml
new file mode 100644
index 0000000..3a49335
--- /dev/null
+++ b/of-save/ctl/conf/findbugs/exclude.xml
@@ -0,0 +1,18 @@
+<FindBugsFilter>
+ <!--
+ Note: Exclusion definition exists in multiple places.
+ - In file ${findbugs.excludeFilterFile} defined at top of pom.xml (this file)
+ - In file conf/checkstyle/onos_suppressions.xml
+ - maven-pmd-plugin configuration in pom.xml
+ (under build and reporting)
+ -->
+ <Match>
+ <Class name="~net\.onrc\.onos\.core\.datastore\.serializers\..*" />
+ </Match>
+ <Match>
+ <Class name="~.*edu\.stanford\..*"/>
+ </Match>
+ <Match>
+ <Class name="~.org\.projectfloodlight\..*"/>
+ </Match>
+</FindBugsFilter>
diff --git a/of-save/ctl/old-pom.xml b/of-save/ctl/old-pom.xml
new file mode 100644
index 0000000..fcdc921
--- /dev/null
+++ b/of-save/ctl/old-pom.xml
@@ -0,0 +1,624 @@
+<?xml version="1.0"?>
+<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>
+ <prerequisites>
+ <maven>3.0.4</maven>
+ </prerequisites>
+ <groupId>net.onrc.onos.of.ctl</groupId>
+ <artifactId>io</artifactId>
+ <version>0.0.1</version>
+ <packaging>bundle</packaging>
+ <name>of-ctl</name>
+ <url>http://onlab.us/</url>
+ <licenses>
+ <license>
+ <name>Apache License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ </license>
+ </licenses>
+ <repositories>
+ <repository>
+ <id>central</id>
+ <name>Maven Central repository</name>
+ <url>https://repo1.maven.org/maven2</url>
+ </repository>
+ <repository>
+ <id>maven-restlet</id>
+ <name>Public online Restlet repository</name>
+ <url>http://maven.restlet.org</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>sonatype-oss-snapshot</id>
+ <name>Sonatype OSS snapshot repository</name>
+ <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ </repository>
+ </repositories>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <powermock.version>1.5.5</powermock.version>
+ <restlet.version>2.1.4</restlet.version>
+ <cobertura-maven-plugin.version>2.6</cobertura-maven-plugin.version>
+ <!-- Following 2 findbugs version needs to be updated in sync to match the
+ findbugs version used in findbugs-plugin -->
+ <findbugs.version>3.0.0</findbugs.version>
+ <findbugs-plugin.version>3.0.0</findbugs-plugin.version>
+ <findbugs.effort>Max</findbugs.effort>
+ <findbugs.excludeFilterFile>${project.basedir}/conf/findbugs/exclude.xml</findbugs.excludeFilterFile>
+ <checkstyle-plugin.version>2.12</checkstyle-plugin.version>
+ <!-- To publish javadoc to github,
+ uncomment com.github.github site-maven-plugin and
+ see https://github.com/OPENNETWORKINGLAB/ONOS/pull/425
+ <github.global.server>github</github.global.server>
+ -->
+ <metrics.version>3.0.2</metrics.version>
+ <maven.surefire.plugin.version>2.16</maven.surefire.plugin.version>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-scr-plugin</artifactId>
+ <version>1.15.0</version>
+ <executions>
+ <execution>
+ <id>generate-scr-srcdescriptor</id>
+ <goals>
+ <goal>scr</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <supportedProjectTypes>
+ <supportedProjectType>bundle</supportedProjectType>
+ <supportedProjectType>war</supportedProjectType>
+ </supportedProjectTypes>
+ </configuration>
+</plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+ </instructions>
+ </configuration>
+ </plugin>
+ <!-- Note: the checkstyle configuration is also in the reporting section -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle-plugin.version}</version>
+ <configuration>
+ <configLocation>${project.basedir}/conf/checkstyle/sun_checks.xml</configLocation>
+ <propertiesLocation>${project.basedir}/conf/checkstyle/checkstyle_maven.properties</propertiesLocation>
+ <failsOnError>false</failsOnError>
+ <logViolationsToConsole>true</logViolationsToConsole>
+ <includeTestSourceDirectory>true</includeTestSourceDirectory>
+ </configuration>
+ <executions>
+ <execution>
+ <id>validate-checkstyle</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.5.1</version>
+ <executions>
+ </executions>
+ </plugin>
+ <!-- guice maven plugin for dependency injection inside maven -->
+ <plugin>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>guice-maven-plugin</artifactId>
+ <version>2.11.0</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.5</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <version>2.8</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ </plugin>
+ <plugin>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.3</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ <encoding>UTF-8</encoding>
+ <showDeprecation>true</showDeprecation>
+ <showWarnings>true</showWarnings>
+ <compilerArgs>
+ <arg>-Xlint:all</arg>
+ <arg>-Xlint:-serial</arg>
+ <arg>-Werror</arg>
+ </compilerArgs>
+ </configuration>
+ <executions>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${maven.surefire.plugin.version}</version>
+ <configuration>
+ <!-- FIXME -XX:-UseSplitVerifier added as workaround for JDK 1.7.0u65 + PowerMock issue
+ https://issues.jboss.org/browse/JASSIST-228 -->
+ <argLine>-XX:MaxPermSize=256m -XX:-UseSplitVerifier</argLine>
+ <redirectTestOutputToFile>false</redirectTestOutputToFile>
+ </configuration>
+ </plugin>
+ <!-- TODO exec:java no longer used remove at some point? -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.2.1</version>
+ <configuration>
+ <mainClass>net.onrc.onos.core.main.Main</mainClass>
+ </configuration>
+ <executions>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <configuration>
+ <charset>UTF-8</charset>
+ <locale>en</locale>
+ <author>false</author>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.4</version>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </plugin>
+ <plugin>
+ <!-- Using groovy script to set maven property ${hostname}.
+ This is a workaround to get hostname as a property inside pom file,
+ which current Maven does not provide. -->
+ <groupId>org.codehaus.gmaven</groupId>
+ <artifactId>groovy-maven-plugin</artifactId>
+ <version>2.0</version>
+ <executions>
+ <execution>
+ <phase>initialize</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <source>
+ project.properties["hostname"] = InetAddress.getLocalHost().getHostName()
+ </source>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.8</version>
+ <executions>
+ <execution>
+ <id>build-classpath</id>
+ <phase>compile</phase>
+ <goals>
+ <goal>build-classpath</goal>
+ </goals>
+ <configuration>
+ <outputFile>${project.basedir}/.javacp.${hostname}</outputFile>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>${cobertura-maven-plugin.version}</version>
+ <configuration>
+ <instrumentation>
+ <ignores>
+ <ignore>org.slf4j.*</ignore>
+ </ignores>
+ </instrumentation>
+ <quiet>true</quiet>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>clean</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <!-- Note: the findbugs configuration is also in the reporting section -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>${findbugs-plugin.version}</version>
+ <configuration>
+ <effort>${findbugs.effort}</effort>
+ <excludeFilterFile>${findbugs.excludeFilterFile}</excludeFilterFile>
+ </configuration>
+ <executions>
+ <execution>
+ <id>validate-findbugs</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <!--
+ Note: Exclusion definition exists in multiple places.
+ - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
+ - In file conf/checkstyle/onos_suppressions.xml
+ - maven-pmd-plugin configuration in pom.xml
+ (under build and reporting)
+ -->
+ <rulesets>
+ <ruleset>${basedir}/conf/pmd/ruleset.xml</ruleset>
+ </rulesets>
+ </configuration>
+ <executions>
+ <execution>
+ <id>validate-pmd</id>
+ <phase>verify</phase>
+ <goals>
+ <!-- Uncomment this goal to make the build fail on pmd errors -->
+ <!--<goal>check</goal>-->
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ org.apache.maven.plugins
+ </groupId>
+ <artifactId>
+ maven-dependency-plugin
+ </artifactId>
+ <versionRange>[2.8,)</versionRange>
+ <goals>
+ <goal>build-classpath</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.codehaus.gmaven</groupId>
+ <artifactId>groovy-maven-plugin</artifactId>
+ <versionRange>[2.0,)</versionRange>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ <!-- for getting visualization reporting -->
+ <reporting>
+ <excludeDefaults>true</excludeDefaults>
+ <outputDirectory>${project.build.directory}/site</outputDirectory>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.7</version>
+ <configuration>
+ <dependencyDetailsEnabled>false</dependencyDetailsEnabled>
+ <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+ </configuration>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>dependencies</report>
+ <report>scm</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.9.1</version>
+ <configuration>
+ <charset>UTF-8</charset>
+ <locale>en</locale>
+ <author>false</author>
+ <excludePackageNames>net.floodlightcontroller.*:net.onrc.onos.core.datastore.serializers</excludePackageNames>
+ </configuration>
+ </plugin>
+ <plugin>
+ <!-- Note: the checkstyle configuration is also in the build section -->
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <version>${checkstyle-plugin.version}</version>
+ <configuration>
+ <configLocation>conf/checkstyle/sun_checks.xml</configLocation>
+ <!--
+ Note: Exclusion definition exists in multiple places.
+ - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
+ - maven-checkstyle-plugin configuration in pom.xml
+ - maven-pmd-plugin configuration in pom.xml
+ (under build and reporting)
+ -->
+ <propertiesLocation>${basedir}/conf/checkstyle/checkstyle_maven.properties</propertiesLocation>
+ <includeTestSourceDirectory>true</includeTestSourceDirectory>
+ </configuration>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>checkstyle</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <!-- Note: the findbugs configuration is also in the build section -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>${findbugs-plugin.version}</version>
+ <configuration>
+ <effort>${findbugs.effort}</effort>
+ <excludeFilterFile>${findbugs.excludeFilterFile}</excludeFilterFile>
+ <reportPlugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ </plugin>
+ </reportPlugins>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <!--
+ Note: Exclusion definition exists in multiple places.
+ - In file ${findbugs.excludeFilterFile} defined at top of pom.xml
+ - In file conf/checkstyle/onos_suppressions.xml
+ - maven-pmd-plugin configuration in pom.xml
+ (under build and reporting)
+ -->
+ <excludes>
+ <exclude>**/datastore/serializers/**</exclude>
+ <exclude>**/edu/stanford/**</exclude>
+ <exclude>**/net/floodlightcontroller/**</exclude>
+ </excludes>
+ <rulesets>
+ <ruleset>${basedir}/conf/pmd/onos_ruleset.xml</ruleset>
+ </rulesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>${cobertura-maven-plugin.version}</version>
+ </plugin>
+ </plugins>
+ </reporting>
+ <dependencies>
+ <!-- ONOS's direct dependencies -->
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ <version>1.9.6</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.5</version>
+ </dependency>
+ <dependency>
+ <!-- findbugs suppression annotation and @GuardedBy, etc. -->
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>annotations</artifactId>
+ <version>${findbugs.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.projectfloodlight</groupId>
+ <artifactId>openflowj</artifactId>
+ <version>0.3.6-SNAPSHOT</version>
+ </dependency>
+ <!-- Floodlight's dependencies -->
+ <dependency>
+ <!-- dependency to old version of netty? -->
+ <groupId>io.netty</groupId>
+ <artifactId>netty</artifactId>
+ <version>3.9.2.Final</version>
+ </dependency>
+ <!-- Dependency for libraries used for testing -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <profiles>
+ <!-- Jenkins by default defines a property BUILD_NUMBER which is used to
+ enable the profile. -->
+ <profile>
+ <id>jenkins</id>
+ <activation>
+ <property>
+ <name>env.BUILD_NUMBER</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>${cobertura-maven-plugin.version}</version>
+ <configuration>
+ <formats>
+ <format>xml</format>
+ </formats>
+ <quiet>true</quiet>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>cobertura</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>all-tests</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${maven.surefire.plugin.version}</version>
+ <configuration combine.self="merge">
+ <excludedGroups></excludedGroups>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>error-prone</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <compilerArgs combine.children="append">
+ <!-- FIXME -Xlint:-path required when using findbugs + error-prone -->
+ <arg>-Xlint:-path</arg>
+ </compilerArgs>
+ <!-- Turn on error-prone -->
+ <compilerId>javac-with-errorprone</compilerId>
+ <forceJavacCompilerUse>true</forceJavacCompilerUse>
+ </configuration>
+ <dependencies combine.children="append">
+ <dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_core</artifactId>
+ <version>1.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-compiler-javac</artifactId>
+ <version>2.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-compiler-javac-errorprone</artifactId>
+ <version>2.3</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+</project>
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/IOFSwitch.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/IOFSwitch.java
new file mode 100644
index 0000000..8015f3f
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/IOFSwitch.java
@@ -0,0 +1,582 @@
+/**
+ * Copyright 2011, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterException;
+import net.onrc.onos.of.ctl.util.OrderedCollection;
+
+import org.jboss.netty.channel.Channel;
+import org.projectfloodlight.openflow.protocol.OFActionType;
+import org.projectfloodlight.openflow.protocol.OFCapabilities;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.types.U64;
+
+
+public interface IOFSwitch {
+
+ /**
+ * OF1.3 switches should support role-request messages as in the 1.3 spec.
+ * OF1.0 switches may or may not support the Nicira role request extensions.
+ * To indicate the support, this property should be set by the associated
+ * OF1.0 switch driver in the net.onrc.onos.core.drivermanager package.
+ * The property will be ignored for OF1.3 switches.
+ */
+ public static final String SWITCH_SUPPORTS_NX_ROLE = "supportsNxRole";
+
+
+ //************************
+ // Channel related
+ //************************
+
+ /**
+ * Disconnects the switch by closing the TCP connection. Results in a call
+ * to the channel handler's channelDisconnected method for cleanup
+ * @throws IOException
+ */
+ public void disconnectSwitch();
+
+ /**
+ * Writes to the OFMessage to the output stream.
+ *
+ * @param m
+ * @param bc
+ * @throws IOException
+ */
+ public void write(OFMessage m) throws IOException;
+
+ /**
+ * Writes the list of messages to the output stream.
+ *
+ * @param msglist
+ * @param bc
+ * @throws IOException
+ */
+ public void write(List<OFMessage> msglist) throws IOException;
+
+ /**
+ * Gets the date the switch connected to this controller.
+ *
+ * @return the date
+ */
+ public Date getConnectedSince();
+
+ /**
+ * Gets the next available transaction id.
+ *
+ * @return the next transaction ID
+ */
+ public int getNextTransactionId();
+
+ /**
+ * Checks if the switch is still connected.
+ * Only call while holding processMessageLock
+ *
+ * @return whether the switch is still disconnected
+ */
+ public boolean isConnected();
+
+ /**
+ * Sets whether the switch is connected.
+ * Only call while holding modifySwitchLock
+ *
+ * @param connected whether the switch is connected
+ */
+ public void setConnected(boolean connected);
+
+ /**
+ * Flushes all flows queued for this switch in the current thread.
+ * NOTE: The contract is limited to the current thread
+ */
+ public void flush();
+
+ /**
+ * Sets the Netty Channel this switch instance is associated with.
+ * <p>
+ * Called immediately after instantiation
+ *
+ * @param channel the channel
+ */
+ public void setChannel(Channel channel);
+
+ //************************
+ // Switch features related
+ //************************
+
+ /**
+ * Gets the datapathId of the switch.
+ *
+ * @return the switch buffers
+ */
+ public long getId();
+
+ /**
+ * Gets a string version of the ID for this switch.
+ *
+ * @return string version of the ID
+ */
+ public String getStringId();
+
+ /**
+ * Gets the number of buffers.
+ *
+ * @return the number of buffers
+ */
+ public int getNumBuffers();
+
+ public Set<OFCapabilities> getCapabilities();
+
+ public byte getNumTables();
+
+ /**
+ * Returns an OFDescStatsReply message object. Use the methods contained
+ * to retrieve switch descriptions for Manufacturer, Hw/Sw version etc.
+ */
+ public OFDescStatsReply getSwitchDescription();
+
+ /**
+ * Cancel features reply with a specific transaction ID.
+ * @param transactionId the transaction ID
+ */
+ public void cancelFeaturesReply(int transactionId);
+
+ /**
+ * Gets the OFActionType set.
+ * <p>
+ * getActions has relevance only for an OpenFlow 1.0 switch.
+ * For OF1.3, each table can support different actions
+ *
+ * @return the action set
+ */
+ public Set<OFActionType> getActions();
+
+ public void setOFVersion(OFVersion ofv);
+
+ public OFVersion getOFVersion();
+
+
+ //************************
+ // Switch port related
+ //************************
+
+ /**
+ * the type of change that happened to an open flow port.
+ */
+ public enum PortChangeType {
+ /** Either a new port has been added by the switch, or we are
+ * adding a port we just deleted (via a prior notification) due to
+ * a change in the portNumber-portName mapping.
+ */
+ ADD,
+ /** some other feature of the port has changed (eg. speed)*/
+ OTHER_UPDATE,
+ /** Either a port has been deleted by the switch, or we are deleting
+ * a port whose portNumber-portName mapping has changed. Note that in
+ * the latter case, a subsequent notification will be sent out to add a
+ * port with the new portNumber-portName mapping.
+ */
+ DELETE,
+ /** Port is up (i.e. enabled). Presumably an earlier notification had
+ * indicated that it was down. To be UP implies that the port is
+ * administratively considered UP (see ofp_port_config) AND the port
+ * link is up AND the port is no longer blocked (see ofp_port_state).
+ */
+ UP,
+ /** Port is down (i.e. disabled). Presumably an earlier notification had
+ * indicated that it was up, or the port was always up.
+ * To be DOWN implies that the port has been either
+ * administratively brought down (see ofp_port_config) OR the port
+ * link is down OR the port is blocked (see ofp_port_state).
+ */
+ DOWN,
+ }
+
+ /**
+ * Describes a change of an open flow port.
+ */
+ public static class PortChangeEvent {
+ public final OFPortDesc port;
+ public final PortChangeType type;
+ /**
+ * @param port
+ * @param type
+ */
+ public PortChangeEvent(OFPortDesc port,
+ PortChangeType type) {
+ this.port = port;
+ this.type = type;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((port == null) ? 0 : port.hashCode());
+ result = prime * result + ((type == null) ? 0 : type.hashCode());
+ return result;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PortChangeEvent other = (PortChangeEvent) obj;
+ if (port == null) {
+ if (other.port != null) {
+ return false;
+ }
+ } else if (!port.equals(other.port)) {
+ return false;
+ }
+ if (type != other.type) {
+ return false;
+ }
+ return true;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "[" + type + " " + port.toString() + "]";
+ }
+ }
+
+
+ /**
+ * Get list of all enabled ports. This will typically be different from
+ * the list of ports in the OFFeaturesReply, since that one is a static
+ * snapshot of the ports at the time the switch connected to the controller
+ * whereas this port list also reflects the port status messages that have
+ * been received.
+ *
+ * @return Unmodifiable list of ports not backed by the underlying collection
+ */
+ public Collection<OFPortDesc> getEnabledPorts();
+
+ /**
+ * Get list of the port numbers of all enabled ports. This will typically
+ * be different from the list of ports in the OFFeaturesReply, since that
+ * one is a static snapshot of the ports at the time the switch connected
+ * to the controller whereas this port list also reflects the port status
+ * messages that have been received.
+ *
+ * @return Unmodifiable list of ports not backed by the underlying collection
+ */
+ public Collection<Integer> getEnabledPortNumbers();
+
+ /**
+ * Retrieve the port object by the port number. The port object
+ * is the one that reflects the port status updates that have been
+ * received, not the one from the features reply.
+ *
+ * @param portNumber
+ * @return port object
+ */
+ public OFPortDesc getPort(int portNumber);
+
+ /**
+ * Retrieve the port object by the port name. The port object
+ * is the one that reflects the port status updates that have been
+ * received, not the one from the features reply.
+ *
+ * @param portName
+ * @return port object
+ */
+ public OFPortDesc getPort(String portName);
+
+ /**
+ * Add or modify a switch port. This is called by the core controller
+ * code in response to a OFPortStatus message.
+ *
+ * OFPPR_MODIFY and OFPPR_ADD will be treated as equivalent. The OpenFlow
+ * spec is not clear on whether portNames are portNumbers are considered
+ * authoritative identifiers. We treat portNames <-> portNumber mappings
+ * as fixed. If they change, we delete all previous conflicting ports and
+ * add all new ports.
+ *
+ * @param ps the port status message
+ * @return the ordered Collection of changes "applied" to the old ports
+ * of the switch according to the PortStatus message. A single PortStatus
+ * message can result in multiple changes.
+ * If portName <-> portNumber mappings have
+ * changed, the iteration order ensures that delete events for old
+ * conflicting appear before before events adding new ports
+ */
+ public OrderedCollection<PortChangeEvent> processOFPortStatus(OFPortStatus ps);
+
+ /**
+ * Get list of all ports. This will typically be different from
+ * the list of ports in the OFFeaturesReply, since that one is a static
+ * snapshot of the ports at the time the switch connected to the controller
+ * whereas this port list also reflects the port status messages that have
+ * been received.
+ *
+ * @return Unmodifiable list of ports
+ */
+ public Collection<OFPortDesc> getPorts();
+
+ /**
+ * @param portName
+ * @return Whether a port is enabled per latest port status message
+ * (not configured down nor link down nor in spanning tree blocking state)
+ */
+ public boolean portEnabled(int portName);
+
+ /**
+ * @param portNumber
+ * @return Whether a port is enabled per latest port status message
+ * (not configured down nor link down nor in spanning tree blocking state)
+ */
+ public boolean portEnabled(String portName);
+
+ /**
+ * Compute the changes that would be required to replace the old ports
+ * of this switch with the new ports.
+ * @param ports new ports to set
+ * @return the ordered collection of changes "applied" to the old ports
+ * of the switch in order to set them to the new set.
+ * If portName <-> portNumber mappings have
+ * changed, the iteration order ensures that delete events for old
+ * conflicting appear before before events adding new ports
+ */
+ public OrderedCollection<PortChangeEvent>
+ comparePorts(Collection<OFPortDesc> ports);
+
+ /**
+ * Replace the ports of this switch with the given ports.
+ * @param ports new ports to set
+ * @return the ordered collection of changes "applied" to the old ports
+ * of the switch in order to set them to the new set.
+ * If portName <-> portNumber mappings have
+ * changed, the iteration order ensures that delete events for old
+ * conflicting appear before before events adding new ports
+ */
+ public OrderedCollection<PortChangeEvent>
+ setPorts(Collection<OFPortDesc> ports);
+
+ //*******************************************
+ // IOFSwitch object attributes
+ //************************
+
+ /**
+ * Gets attributes of this switch.
+ *
+ * @return attributes of the switch
+ */
+ public Map<Object, Object> getAttributes();
+
+ /**
+ * Checks if a specific switch property exists for this switch.
+ *
+ * @param name name of property
+ * @return value for name
+ */
+ boolean hasAttribute(String name);
+
+ /**
+ * Gets properties for switch specific behavior.
+ *
+ * @param name name of property
+ * @return 'value' for 'name', or null if no entry for 'name' exists
+ */
+ Object getAttribute(String name);
+
+ /**
+ * Sets properties for switch specific behavior.
+ *
+ * @param name name of property
+ * @param value value for name
+ */
+ void setAttribute(String name, Object value);
+
+ /**
+ * Removes properties for switch specific behavior.
+ *
+ * @param name name of property
+ * @return current value for name or null (if not present)
+ */
+ Object removeAttribute(String name);
+
+ //************************
+ // Switch statistics
+ //************************
+
+ /**
+ * Delivers the statistics future reply.
+ *
+ * @param reply the reply to deliver
+ */
+ public void deliverStatisticsReply(OFMessage reply);
+
+ /**
+ * Cancels the statistics reply with the given transaction ID.
+ *
+ * @param transactionId the transaction ID
+ */
+ public void cancelStatisticsReply(int transactionId);
+
+ /**
+ * Cancels all statistics replies.
+ */
+ public void cancelAllStatisticsReplies();
+
+ /**
+ * Gets a Future object that can be used to retrieve the asynchronous.
+ * OFStatisticsReply when it is available.
+ *
+ * @param request statistics request
+ * @return Future object wrapping OFStatisticsReply
+ * @throws IOException
+ */
+ public Future<List<OFStatsReply>> getStatistics(OFStatsRequest<?> request)
+ throws IOException;
+
+ //************************
+ // Switch other utilities
+ //************************
+
+ /**
+ * Clears all flowmods on this switch.
+ */
+ public void clearAllFlowMods();
+
+ /**
+ * Gets the current role of this controller for this IOFSwitch.
+ */
+ public Role getRole();
+
+ /**
+ * Sets this controller's Role for this IOFSwitch to role.
+ *
+ * @param role
+ */
+ public void setRole(Role role);
+
+ /**
+ * Gets the next generation ID.
+ * <p>
+ * Note: relevant for role request messages in OF1.3
+ *
+ * @return next generation ID
+ */
+ public U64 getNextGenerationId();
+
+
+ /**
+ * Set debug counter service for per-switch counters.
+ * Called immediately after instantiation.
+ * @param debugCounters
+ * @throws CounterException
+ */
+ public void setDebugCounterService(IDebugCounterService debugCounter)
+ throws CounterException;
+
+ /**
+ * Start this switch driver's sub handshake. This might be a no-op but
+ * this method must be called at least once for the switch to be become
+ * ready.
+ * This method must only be called from the I/O thread
+ * @throws IOException
+ * @throws SwitchDriverSubHandshakeAlreadyStarted if the sub-handshake has
+ * already been started
+ */
+ public void startDriverHandshake() throws IOException;
+
+ /**
+ * Check if the sub-handshake for this switch driver has been completed.
+ * This method can only be called after startDriverHandshake()
+ *
+ * This methods must only be called from the I/O thread
+ * @return true if the sub-handshake has been completed. False otherwise
+ * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has
+ * not been called yet.
+ */
+ public boolean isDriverHandshakeComplete();
+
+ /**
+ * Pass the given OFMessage to the driver as part of this driver's
+ * sub-handshake. Must not be called after the handshake has been completed
+ * This methods must only be called from the I/O thread
+ * @param m The message that the driver should process
+ * @throws SwitchDriverSubHandshakeCompleted if isDriverHandshake() returns
+ * false before this method call
+ * @throws SwitchDriverSubHandshakeNotStarted if startDriverHandshake() has
+ * not been called yet.
+ */
+ public void processDriverHandshakeMessage(OFMessage m);
+
+ /**
+ * Set the flow table full flag in the switch.
+ * XXX S Rethink this for multiple tables
+ */
+ public void setTableFull(boolean isFull);
+
+ /**
+ * Save the features reply for this switch.
+ *
+ * @param featuresReply
+ */
+ public void setFeaturesReply(OFFeaturesReply featuresReply);
+
+ /**
+ * Save the portset for this switch.
+ *
+ * @param portDescReply
+ */
+ public void setPortDescReply(OFPortDescStatsReply portDescReply);
+
+ //************************
+ // Message handling
+ //************************
+ /**
+ * Handle the message coming from the dataplane.
+ *
+ * @param m the actual message
+ */
+ public void handleMessage(OFMessage m);
+
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/IOFSwitchManager.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/IOFSwitchManager.java
new file mode 100644
index 0000000..b3b8ed3
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/IOFSwitchManager.java
@@ -0,0 +1,33 @@
+package net.onrc.onos.of.ctl;
+
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+import net.onrc.onos.of.ctl.registry.IControllerRegistry;
+
+/**
+ * Interface to passed to controller class in order to allow
+ * it to spawn the appropriate type of switch and furthermore
+ * specify a registry object (ie. ZooKeeper).
+ *
+ */
+public interface IOFSwitchManager {
+
+ /**
+ * Given a description string for a switch spawn the
+ * concrete representation of that switch.
+ *
+ * @param mfr manufacturer description
+ * @param hwDesc hardware description
+ * @param swDesc software description
+ * @param ofv openflow version
+ * @return A switch of type IOFSwitch.
+ */
+ public IOFSwitch getSwitchImpl(String mfr, String hwDesc, String swDesc, OFVersion ofv);
+
+ /**
+ * Returns the mastership registry used during controller-switch role election.
+ * @return the registry
+ */
+ public IControllerRegistry getRegistry();
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/Role.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/Role.java
new file mode 100644
index 0000000..d892161
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/Role.java
@@ -0,0 +1,36 @@
+package net.onrc.onos.of.ctl;
+
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+
+/**
+ * The role of the controller as it pertains to a particular switch.
+ * Note that this definition of the role enum is different from the
+ * OF1.3 definition. It is maintained here to be backward compatible to
+ * earlier versions of the controller code. This enum is translated
+ * to the OF1.3 enum, before role messages are sent to the switch.
+ * See sendRoleRequestMessage method in OFSwitchImpl
+ */
+public enum Role {
+ EQUAL(OFControllerRole.ROLE_EQUAL),
+ MASTER(OFControllerRole.ROLE_MASTER),
+ SLAVE(OFControllerRole.ROLE_SLAVE);
+
+ private Role(OFControllerRole nxRole) {
+ nxRole.ordinal();
+ }
+ /*
+ private static Map<Integer,Role> nxRoleToEnum
+ = new HashMap<Integer,Role>();
+ static {
+ for(Role r: Role.values())
+ nxRoleToEnum.put(r.toNxRole(), r);
+ }
+ public int toNxRole() {
+ return nxRole;
+ }
+ // Return the enum representing the given nxRole or null if no
+ // such role exists
+ public static Role fromNxRole(int nxRole) {
+ return nxRoleToEnum.get(nxRole);
+ }*/
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageCategory.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageCategory.java
new file mode 100644
index 0000000..37ac321
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageCategory.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright 2012, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to set the category for log messages for a class.
+ *
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+public @interface LogMessageCategory {
+
+ /**
+ * The category for the log messages for this class.
+ *
+ * @return
+ */
+ String value() default "Core";
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageDoc.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageDoc.java
new file mode 100644
index 0000000..313e074
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageDoc.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2012, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to document log messages. This can be used to generate
+ * documentation on syslog output.
+ *
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+public @interface LogMessageDoc {
+ public static final String NO_ACTION = "No action is required.";
+ public static final String UNKNOWN_ERROR = "An unknown error occured";
+ public static final String GENERIC_ACTION =
+ "Examine the returned error or exception and take " +
+ "appropriate action.";
+ public static final String CHECK_SWITCH =
+ "Check the health of the indicated switch. " +
+ "Test and troubleshoot IP connectivity.";
+ public static final String CHECK_CONTROLLER =
+ "Verify controller system health, CPU usage, and memory. " +
+ "Rebooting the controller node may help if the controller " +
+ "node is in a distressed state.";
+ public static final String REPORT_CONTROLLER_BUG =
+ "This is likely a defect in the controller. Please report this " +
+ "issue. Restarting the controller or switch may help to " +
+ "alleviate.";
+ public static final String REPORT_SWITCH_BUG =
+ "This is likely a defect in the switch. Please report this " +
+ "issue. Restarting the controller or switch may help to " +
+ "alleviate.";
+
+ /**
+ * The log level for the log message.
+ *
+ * @return the log level as a tring
+ */
+ String level() default "INFO";
+
+ /**
+ * The message that will be printed.
+ *
+ * @return the message
+ */
+ String message() default UNKNOWN_ERROR;
+
+ /**
+ * An explanation of the meaning of the log message.
+ *
+ * @return the explanation
+ */
+ String explanation() default UNKNOWN_ERROR;
+
+ /**
+ * The recommendated action associated with the log message.
+ *
+ * @return the recommendation
+ */
+ String recommendation() default NO_ACTION;
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageDocs.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageDocs.java
new file mode 100644
index 0000000..74d4405
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/annotations/LogMessageDocs.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright 2012, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation used to document log messages. This can be used to generate
+ * documentation on syslog output. This version allows multiple log messages
+ * to be documentated on an interface.
+ *
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+public @interface LogMessageDocs {
+ /**
+ * A list of {@link LogMessageDoc} elements.
+ *
+ * @return the list of log message doc
+ */
+ LogMessageDoc[] value();
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/DebugCounter.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/DebugCounter.java
new file mode 100644
index 0000000..6ea380c
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/DebugCounter.java
@@ -0,0 +1,726 @@
+package net.onrc.onos.of.ctl.debugcounter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import com.google.common.collect.Sets;
+
+
+
+/**
+ * This class implements a central store for all counters used for debugging the
+ * system. For counters based on traffic-type, see ICounterStoreService.
+ *
+ */
+public class DebugCounter implements IDebugCounterService {
+ protected static final Logger log = LoggerFactory.getLogger(DebugCounter.class);
+
+ /**
+ * registered counters need a counter id.
+ */
+ protected AtomicInteger counterIdCounter = new AtomicInteger();
+
+ /**
+ * The counter value.
+ */
+ protected static class MutableLong {
+ long value = 0;
+ public void increment() { value += 1; }
+ public void increment(long incr) { value += incr; }
+ public long get() { return value; }
+ public void set(long val) { value = val; }
+ }
+
+ /**
+ * protected class to store counter information.
+ */
+ public static class CounterInfo {
+ String moduleCounterHierarchy;
+ String counterDesc;
+ CounterType ctype;
+ String moduleName;
+ String counterHierarchy;
+ int counterId;
+ boolean enabled;
+ String[] metaData;
+
+ public CounterInfo(int counterId, boolean enabled,
+ String moduleName, String counterHierarchy,
+ String desc, CounterType ctype, String... metaData) {
+ this.moduleCounterHierarchy = moduleName + "/" + counterHierarchy;
+ this.moduleName = moduleName;
+ this.counterHierarchy = counterHierarchy;
+ this.counterDesc = desc;
+ this.ctype = ctype;
+ this.counterId = counterId;
+ this.enabled = enabled;
+ this.metaData = metaData;
+ }
+
+ public String getModuleCounterHierarchy() { return moduleCounterHierarchy; }
+ public String getCounterDesc() { return counterDesc; }
+ public CounterType getCtype() { return ctype; }
+ public String getModuleName() { return moduleName; }
+ public String getCounterHierarchy() { return counterHierarchy; }
+ public int getCounterId() { return counterId; }
+ public boolean isEnabled() { return enabled; }
+ public String[] getMetaData() { return this.metaData.clone(); }
+ }
+
+ //******************
+ // Global stores
+ //******************
+
+ /**
+ * Counter info for a debug counter.
+ */
+ public static class DebugCounterInfo {
+ CounterInfo cinfo;
+ AtomicLong cvalue;
+
+ public DebugCounterInfo(CounterInfo cinfo) {
+ this.cinfo = cinfo;
+ this.cvalue = new AtomicLong();
+ }
+ public CounterInfo getCounterInfo() {
+ return cinfo;
+ }
+ public Long getCounterValue() {
+ return cvalue.get();
+ }
+ }
+
+ /**
+ * Global debug-counter storage across all threads. These are
+ * updated from the local per thread counters by the flush counters method.
+ */
+ private static final DebugCounterInfo[] ALLCOUNTERS =
+ new DebugCounterInfo[MAX_COUNTERS];
+
+
+ /**
+ * per module counters, indexed by the module name and storing three levels
+ * of Counter information in the form of CounterIndexStore.
+ */
+ protected ConcurrentHashMap<String, ConcurrentHashMap<String, CounterIndexStore>>
+ moduleCounters = new ConcurrentHashMap<String,
+ ConcurrentHashMap<String,
+ CounterIndexStore>>();
+
+ protected static class CounterIndexStore {
+ int index;
+ Map<String, CounterIndexStore> nextLevel;
+
+ public CounterIndexStore(int index, Map<String, CounterIndexStore> cis) {
+ this.index = index;
+ this.nextLevel = cis;
+ }
+ }
+
+ /**
+ * fast global cache for counter ids that are currently active.
+ */
+ protected Set<Integer> currentCounters = Collections.newSetFromMap(
+ new ConcurrentHashMap<Integer, Boolean>());
+
+ //******************
+ // Thread local stores
+ //******************
+
+ /**
+ * Thread local storage of counter info.
+ */
+ protected static class LocalCounterInfo {
+ boolean enabled;
+ MutableLong cvalue;
+
+ public LocalCounterInfo(boolean enabled) {
+ this.enabled = enabled;
+ this.cvalue = new MutableLong();
+ }
+ }
+
+ /**
+ * Thread local debug counters used for maintaining counters local to a thread.
+ */
+ protected final ThreadLocal<LocalCounterInfo[]> threadlocalCounters =
+ new ThreadLocal<LocalCounterInfo[]>() {
+ @Override
+ protected LocalCounterInfo[] initialValue() {
+ return new LocalCounterInfo[MAX_COUNTERS];
+ }
+ };
+
+ /**
+ * Thread local cache for counter ids that are currently active.
+ */
+ protected final ThreadLocal<Set<Integer>> threadlocalCurrentCounters =
+ new ThreadLocal<Set<Integer>>() {
+ @Override
+ protected Set<Integer> initialValue() {
+ return new HashSet<Integer>();
+ }
+ };
+
+ //*******************************
+ // IDebugCounter
+ //*******************************
+
+ protected class CounterImpl implements IDebugCounter {
+ private final int counterId;
+
+ public CounterImpl(int counterId) {
+ this.counterId = counterId;
+ }
+
+ @Override
+ public void updateCounterWithFlush() {
+ if (!validCounterId()) {
+ return;
+ }
+ updateCounter(counterId, 1, true);
+ }
+
+ @Override
+ public void updateCounterNoFlush() {
+ if (!validCounterId()) {
+ return;
+ }
+ updateCounter(counterId, 1, false);
+ }
+
+ @Override
+ public void updateCounterWithFlush(int incr) {
+ if (!validCounterId()) {
+ return;
+ }
+ updateCounter(counterId, incr, true);
+ }
+
+ @Override
+ public void updateCounterNoFlush(int incr) {
+ if (!validCounterId()) {
+ return;
+ }
+ updateCounter(counterId, incr, false);
+ }
+
+ @Override
+ public long getCounterValue() {
+ if (!validCounterId()) {
+ return -1;
+ }
+ return ALLCOUNTERS[counterId].cvalue.get();
+ }
+
+ /**
+ * Checks if this is a valid counter.
+ * @return true if the counter id is valid
+ */
+ private boolean validCounterId() {
+ if (counterId < 0 || counterId >= MAX_COUNTERS) {
+ log.error("Invalid counterId invoked");
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+ //*******************************
+ // IDebugCounterService
+ //*******************************
+
+ @Override
+ public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
+ String counterDescription, CounterType counterType,
+ String... metaData)
+ throws CounterException {
+ // check if counter already exists
+ if (!moduleCounters.containsKey(moduleName)) {
+ moduleCounters.putIfAbsent(moduleName,
+ new ConcurrentHashMap<String, CounterIndexStore>());
+ }
+ RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
+ if (rci.allLevelsFound) {
+ // counter exists
+ log.info("Counter exists for {}/{} -- resetting counters", moduleName,
+ counterHierarchy);
+ resetCounterHierarchy(moduleName, counterHierarchy);
+ return new CounterImpl(rci.ctrIds[rci.foundUptoLevel - 1]);
+ }
+ // check for validity of counter
+ if (rci.levels.length > MAX_HIERARCHY) {
+ String err = "Registry of counterHierarchy " + counterHierarchy +
+ " exceeds max hierachy " + MAX_HIERARCHY + ".. aborting";
+ throw new MaxHierarchyRegistered(err);
+ }
+ if (rci.foundUptoLevel < rci.levels.length - 1) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i <= rci.foundUptoLevel; i++) {
+ sb.append(rci.levels[i]);
+ }
+ String needToRegister = sb.toString();
+ String err = "Attempting to register hierarchical counterHierarchy " +
+ counterHierarchy + " but parts of hierarchy missing. " +
+ "Please register " + needToRegister + " first";
+ throw new MissingHierarchicalLevel(err);
+ }
+
+ // get a new counter id
+ int counterId = counterIdCounter.getAndIncrement();
+ if (counterId >= MAX_COUNTERS) {
+ throw new MaxCountersRegistered("max counters reached");
+ }
+ // create storage for counter
+ boolean enabled = (counterType == CounterType.ALWAYS_COUNT) ? true : false;
+ CounterInfo ci = new CounterInfo(counterId, enabled, moduleName,
+ counterHierarchy, counterDescription,
+ counterType, metaData);
+ ALLCOUNTERS[counterId] = new DebugCounterInfo(ci);
+
+ // account for the new counter in the module counter hierarchy
+ addToModuleCounterHierarchy(moduleName, counterId, rci);
+
+ // finally add to active counters
+ if (enabled) {
+ currentCounters.add(counterId);
+ }
+ return new CounterImpl(counterId);
+ }
+
+ private void updateCounter(int counterId, int incr, boolean flushNow) {
+ if (counterId < 0 || counterId >= MAX_COUNTERS) {
+ return;
+ }
+
+ LocalCounterInfo[] thiscounters = this.threadlocalCounters.get();
+ if (thiscounters[counterId] == null) {
+ // seeing this counter for the first time in this thread - create local
+ // store by consulting global store
+ DebugCounterInfo dc = ALLCOUNTERS[counterId];
+ if (dc != null) {
+ thiscounters[counterId] = new LocalCounterInfo(dc.cinfo.enabled);
+ if (dc.cinfo.enabled) {
+ Set<Integer> thisset = this.threadlocalCurrentCounters.get();
+ thisset.add(counterId);
+ }
+ } else {
+ log.error("updateCounter seen locally for counter {} but no global"
+ + "storage exists for it yet .. not updating", counterId);
+ return;
+ }
+ }
+
+ // update local store if enabled locally for updating
+ LocalCounterInfo lc = thiscounters[counterId];
+ if (lc.enabled) {
+ lc.cvalue.increment(incr);
+ if (flushNow) {
+ DebugCounterInfo dc = ALLCOUNTERS[counterId];
+ if (dc.cinfo.enabled) {
+ // globally enabled - flush now
+ dc.cvalue.addAndGet(lc.cvalue.get());
+ lc.cvalue.set(0);
+ } else {
+ // global counter is disabled - don't flush, disable locally
+ lc.enabled = false;
+ Set<Integer> thisset = this.threadlocalCurrentCounters.get();
+ thisset.remove(counterId);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void flushCounters() {
+ LocalCounterInfo[] thiscounters = this.threadlocalCounters.get();
+ Set<Integer> thisset = this.threadlocalCurrentCounters.get();
+ ArrayList<Integer> temp = new ArrayList<Integer>();
+
+ for (int counterId : thisset) {
+ LocalCounterInfo lc = thiscounters[counterId];
+ if (lc.cvalue.get() > 0) {
+ DebugCounterInfo dc = ALLCOUNTERS[counterId];
+ if (dc.cinfo.enabled) {
+ // globally enabled - flush now
+ dc.cvalue.addAndGet(lc.cvalue.get());
+ lc.cvalue.set(0);
+ } else {
+ // global counter is disabled - don't flush, disable locally
+ lc.enabled = false;
+ temp.add(counterId);
+ }
+ }
+ }
+ for (int cId : temp) {
+ thisset.remove(cId);
+ }
+
+ // At this point it is possible that the thread-local set does not
+ // include a counter that has been enabled and is present in the global set.
+ // We need to sync thread-local currently enabled set of counterIds with
+ // the global set.
+ Sets.SetView<Integer> sv = Sets.difference(currentCounters, thisset);
+ for (int counterId : sv) {
+ if (thiscounters[counterId] != null) {
+ thiscounters[counterId].enabled = true;
+ thisset.add(counterId);
+ }
+ }
+ }
+
+ @Override
+ public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
+ RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
+ if (!rci.allLevelsFound) {
+ String missing = rci.levels[rci.foundUptoLevel];
+ log.error("Cannot reset counter hierarchy - missing counter {}", missing);
+ return;
+ }
+ // reset at this level
+ ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]].cvalue.set(0);
+ // reset all levels below
+ ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
+ for (int index : resetIds) {
+ ALLCOUNTERS[index].cvalue.set(0);
+ }
+ }
+
+ @Override
+ public void resetAllCounters() {
+ RetCtrInfo rci = new RetCtrInfo();
+ rci.levels = "".split("/");
+ for (String moduleName : moduleCounters.keySet()) {
+ ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
+ for (int index : resetIds) {
+ ALLCOUNTERS[index].cvalue.set(0);
+ }
+ }
+ }
+
+ @Override
+ public void resetAllModuleCounters(String moduleName) {
+ Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
+ RetCtrInfo rci = new RetCtrInfo();
+ rci.levels = "".split("/");
+
+ if (target != null) {
+ ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
+ for (int index : resetIds) {
+ ALLCOUNTERS[index].cvalue.set(0);
+ }
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("No module found with name {}", moduleName);
+ }
+ }
+ }
+
+ @Override
+ public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
+ RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
+ if (!rci.allLevelsFound) {
+ String missing = rci.levels[rci.foundUptoLevel];
+ log.error("Cannot enable counter - counter not found {}", missing);
+ return;
+ }
+ // enable specific counter
+ DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
+ dc.cinfo.enabled = true;
+ currentCounters.add(dc.cinfo.counterId);
+ }
+
+ @Override
+ public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
+ RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
+ if (!rci.allLevelsFound) {
+ String missing = rci.levels[rci.foundUptoLevel];
+ log.error("Cannot disable counter - counter not found {}", missing);
+ return;
+ }
+ // disable specific counter
+ DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
+ if (dc.cinfo.ctype == CounterType.COUNT_ON_DEMAND) {
+ dc.cinfo.enabled = false;
+ dc.cvalue.set(0);
+ currentCounters.remove(dc.cinfo.counterId);
+ }
+ }
+
+ @Override
+ public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
+ String counterHierarchy) {
+ RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
+ if (!rci.allLevelsFound) {
+ String missing = rci.levels[rci.foundUptoLevel];
+ log.error("Cannot fetch counter - counter not found {}", missing);
+ return Collections.emptyList();
+ }
+ ArrayList<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
+ // get counter and all below it
+ DebugCounterInfo dc = ALLCOUNTERS[rci.ctrIds[rci.foundUptoLevel - 1]];
+ dcilist.add(dc);
+ ArrayList<Integer> belowIds = getHierarchyBelow(moduleName, rci);
+ for (int index : belowIds) {
+ dcilist.add(ALLCOUNTERS[index]);
+ }
+ return dcilist;
+ }
+
+ @Override
+ public List<DebugCounterInfo> getAllCounterValues() {
+ List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
+ RetCtrInfo rci = new RetCtrInfo();
+ rci.levels = "".split("/");
+
+ for (String moduleName : moduleCounters.keySet()) {
+ ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
+ for (int index : resetIds) {
+ dcilist.add(ALLCOUNTERS[index]);
+ }
+ }
+ return dcilist;
+ }
+
+ @Override
+ public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
+ List<DebugCounterInfo> dcilist = new ArrayList<DebugCounterInfo>();
+ RetCtrInfo rci = new RetCtrInfo();
+ rci.levels = "".split("/");
+
+ if (moduleCounters.containsKey(moduleName)) {
+ ArrayList<Integer> resetIds = getHierarchyBelow(moduleName, rci);
+ for (int index : resetIds) {
+ dcilist.add(ALLCOUNTERS[index]);
+ }
+ }
+ return dcilist;
+ }
+
+ @Override
+ public boolean containsModuleCounterHierarchy(String moduleName,
+ String counterHierarchy) {
+ if (!moduleCounters.containsKey(moduleName)) {
+ return false;
+ }
+ RetCtrInfo rci = getCounterId(moduleName, counterHierarchy);
+ return rci.allLevelsFound;
+ }
+
+ @Override
+ public boolean containsModuleName(String moduleName) {
+ return (moduleCounters.containsKey(moduleName)) ? true : false;
+ }
+
+ @Override
+ public List<String> getModuleList() {
+ List<String> retval = new ArrayList<String>();
+ retval.addAll(moduleCounters.keySet());
+ return retval;
+ }
+
+ @Override
+ public List<String> getModuleCounterList(String moduleName) {
+ if (!moduleCounters.containsKey(moduleName)) {
+ return Collections.emptyList();
+ }
+
+ List<String> retval = new ArrayList<String>();
+ RetCtrInfo rci = new RetCtrInfo();
+ rci.levels = "".split("/");
+
+ ArrayList<Integer> cids = getHierarchyBelow(moduleName, rci);
+ for (int index : cids) {
+ retval.add(ALLCOUNTERS[index].cinfo.counterHierarchy);
+ }
+ return retval;
+ }
+
+ //*******************************
+ // Internal Methods
+ //*******************************
+
+ protected class RetCtrInfo {
+ boolean allLevelsFound; // counter indices found all the way down the hierarchy
+ boolean hierarchical; // true if counterHierarchy is hierarchical
+ int foundUptoLevel;
+ int[] ctrIds;
+ String[] levels;
+
+ public RetCtrInfo() {
+ ctrIds = new int[MAX_HIERARCHY];
+ for (int i = 0; i < MAX_HIERARCHY; i++) {
+ ctrIds[i] = -1;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + getOuterType().hashCode();
+ result = prime * result + (allLevelsFound ? 1231 : 1237);
+ result = prime * result + Arrays.hashCode(ctrIds);
+ result = prime * result + foundUptoLevel;
+ result = prime * result + (hierarchical ? 1231 : 1237);
+ result = prime * result + Arrays.hashCode(levels);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object oth) {
+ if (!(oth instanceof RetCtrInfo)) {
+ return false;
+ }
+ RetCtrInfo other = (RetCtrInfo) oth;
+ if (other.allLevelsFound != this.allLevelsFound) {
+ return false;
+ }
+ if (other.hierarchical != this.hierarchical) {
+ return false;
+ }
+ if (other.foundUptoLevel != this.foundUptoLevel) {
+ return false;
+ }
+ if (!Arrays.equals(other.ctrIds, this.ctrIds)) {
+ return false;
+ }
+ if (!Arrays.equals(other.levels, this.levels)) {
+ return false;
+ }
+ return true;
+ }
+
+ private DebugCounter getOuterType() {
+ return DebugCounter.this;
+ }
+
+
+
+ }
+
+ protected RetCtrInfo getCounterId(String moduleName, String counterHierarchy) {
+ RetCtrInfo rci = new RetCtrInfo();
+ Map<String, CounterIndexStore> templevel = moduleCounters.get(moduleName);
+ rci.levels = counterHierarchy.split("/");
+ if (rci.levels.length > 1) {
+ rci.hierarchical = true;
+ }
+ if (templevel == null) {
+ log.error("moduleName {} does not exist in debugCounters", moduleName);
+ return rci;
+ }
+
+ /*
+ if (rci.levels.length > MAX_HIERARCHY) {
+ // chop off all array elems greater that MAX_HIERARCHY
+ String[] temp = new String[MAX_HIERARCHY];
+ System.arraycopy(rci.levels, 0, temp, 0, MAX_HIERARCHY);
+ rci.levels = temp;
+ }
+ */
+ for (int i = 0; i < rci.levels.length; i++) {
+ if (templevel != null) {
+ CounterIndexStore cis = templevel.get(rci.levels[i]);
+ if (cis == null) {
+ // could not find counterHierarchy part at this level
+ break;
+ } else {
+ rci.ctrIds[i] = cis.index;
+ templevel = cis.nextLevel;
+ rci.foundUptoLevel++;
+ if (i == rci.levels.length - 1) {
+ rci.allLevelsFound = true;
+ }
+ }
+ } else {
+ // there are no more levels, which means that some part of the
+ // counterHierarchy has no corresponding map
+ break;
+ }
+ }
+ return rci;
+ }
+
+ protected void addToModuleCounterHierarchy(String moduleName, int counterId,
+ RetCtrInfo rci) {
+ Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
+ if (target == null) {
+ return;
+ }
+ CounterIndexStore cis = null;
+
+ for (int i = 0; i < rci.foundUptoLevel; i++) {
+ cis = target.get(rci.levels[i]);
+ target = cis.nextLevel;
+ }
+ if (cis != null) {
+ if (cis.nextLevel == null) {
+ cis.nextLevel = new ConcurrentHashMap<String, CounterIndexStore>();
+ }
+ cis.nextLevel.put(rci.levels[rci.foundUptoLevel],
+ new CounterIndexStore(counterId, null));
+ } else {
+ target.put(rci.levels[rci.foundUptoLevel],
+ new CounterIndexStore(counterId, null));
+ }
+ }
+
+ // given a partial hierarchical counter, return the rest of the hierarchy
+ protected ArrayList<Integer> getHierarchyBelow(String moduleName, RetCtrInfo rci) {
+ Map<String, CounterIndexStore> target = moduleCounters.get(moduleName);
+ CounterIndexStore cis = null;
+ ArrayList<Integer> retval = new ArrayList<Integer>();
+ if (target == null) {
+ return retval;
+ }
+
+ // get to the level given
+ for (int i = 0; i < rci.foundUptoLevel; i++) {
+ cis = target.get(rci.levels[i]);
+ target = cis.nextLevel;
+ }
+
+ if (target == null || rci.foundUptoLevel == MAX_HIERARCHY) {
+ // no more levels
+ return retval;
+ } else {
+ // recursively get all ids
+ getIdsAtLevel(target, retval, rci.foundUptoLevel + 1);
+ }
+
+ return retval;
+ }
+
+ protected void getIdsAtLevel(Map<String, CounterIndexStore> hcy,
+ ArrayList<Integer> retval, int level) {
+ if (level > MAX_HIERARCHY) {
+ return;
+ }
+ if (hcy == null || retval == null) {
+ return;
+ }
+
+ // Can return the counter names as well but for now ids are enough.
+ for (CounterIndexStore cistemp : hcy.values()) {
+ retval.add(cistemp.index); // value at this level
+ if (cistemp.nextLevel != null) {
+ getIdsAtLevel(cistemp.nextLevel, retval, level + 1);
+ }
+ }
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/IDebugCounter.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/IDebugCounter.java
new file mode 100644
index 0000000..e157cf2
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/IDebugCounter.java
@@ -0,0 +1,38 @@
+package net.onrc.onos.of.ctl.debugcounter;
+
+public interface IDebugCounter {
+ /**
+ * Increments the counter by 1 thread-locally, and immediately flushes to
+ * the global counter storage. This method should be used for counters that
+ * are updated outside the OF message processing pipeline.
+ */
+ void updateCounterWithFlush();
+
+ /**
+ * Increments the counter by 1 thread-locally. Flushing to the global
+ * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
+ * resulting in higher performance. This method should be used for counters
+ * updated in the OF message processing pipeline.
+ */
+ void updateCounterNoFlush();
+
+ /**
+ * Increments the counter thread-locally by the 'incr' specified, and immediately
+ * flushes to the global counter storage. This method should be used for counters
+ * that are updated outside the OF message processing pipeline.
+ */
+ void updateCounterWithFlush(int incr);
+
+ /**
+ * Increments the counter thread-locally by the 'incr' specified. Flushing to the global
+ * counter storage is delayed (happens with flushCounters() in IDebugCounterService),
+ * resulting in higher performance. This method should be used for counters
+ * updated in the OF message processing pipeline.
+ */
+ void updateCounterNoFlush(int incr);
+
+ /**
+ * Retrieve the value of the counter from the global counter store.
+ */
+ long getCounterValue();
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/IDebugCounterService.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/IDebugCounterService.java
new file mode 100644
index 0000000..81a80b1
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/IDebugCounterService.java
@@ -0,0 +1,260 @@
+package net.onrc.onos.of.ctl.debugcounter;
+
+
+
+import java.util.List;
+
+import net.onrc.onos.of.ctl.debugcounter.DebugCounter.DebugCounterInfo;
+
+public interface IDebugCounterService {
+
+ /**
+ * Different counter types. Counters that are meant to be counted-on-demand
+ * need to be separately enabled/disabled.
+ */
+ public enum CounterType {
+ ALWAYS_COUNT,
+ COUNT_ON_DEMAND
+ }
+
+ /**
+ * Debug Counter Qualifiers.
+ */
+ public static final String CTR_MDATA_WARN = "warn";
+ public static final String CTR_MDATA_ERROR = "error";
+ public static final String CTR_MDATA_DROP = "drop";
+
+ /**
+ * A limit on the maximum number of counters that can be created.
+ */
+ public static final int MAX_COUNTERS = 5000;
+
+ /**
+ * Exception thrown when MAX_COUNTERS have been registered.
+ */
+ public class MaxCountersRegistered extends CounterException {
+ private static final long serialVersionUID = 3173747663719376745L;
+ String errormsg;
+ public MaxCountersRegistered(String errormsg) {
+ this.errormsg = errormsg;
+ }
+ @Override
+ public String getMessage() {
+ return this.errormsg;
+ }
+ }
+ /**
+ * Exception thrown when MAX_HIERARCHY has been reached.
+ */
+ public class MaxHierarchyRegistered extends CounterException {
+ private static final long serialVersionUID = 967431358683523871L;
+ private String errormsg;
+ public MaxHierarchyRegistered(String errormsg) {
+ this.errormsg = errormsg;
+ }
+ @Override
+ public String getMessage() {
+ return this.errormsg;
+ }
+ }
+ /**
+ * Exception thrown when attempting to register a hierarchical counter
+ * where higher levels of the hierarchy have not been pre-registered.
+ */
+ public class MissingHierarchicalLevel extends CounterException {
+ private static final long serialVersionUID = 517315311533995739L;
+ private String errormsg;
+ public MissingHierarchicalLevel(String errormsg) {
+ this.errormsg = errormsg;
+ }
+ @Override
+ public String getMessage() {
+ return this.errormsg;
+ }
+ }
+
+ public class CounterException extends Exception {
+ private static final long serialVersionUID = 2219781500857866035L;
+ }
+
+ /**
+ * maximum levels of hierarchy.
+ * Example of moduleName/counterHierarchy:
+ * switch/00:00:00:00:01:02:03:04/pktin/drops where
+ * moduleName ==> "switch" and
+ * counterHierarchy of 3 ==> "00:00:00:00:01:02:03:04/pktin/drops"
+ */
+ public static final int MAX_HIERARCHY = 3;
+
+ /**
+ * All modules that wish to have the DebugCounterService count for them, must
+ * register their counters by making this call (typically from that module's
+ * 'startUp' method). The counter can then be updated, displayed, reset etc.
+ * using the registered moduleName and counterHierarchy.
+ *
+ * @param moduleName the name of the module which is registering the
+ * counter eg. linkdiscovery or controller or switch
+ * @param counterHierarchy the hierarchical counter name specifying all
+ * the hierarchical levels that come above it.
+ * For example: to register a drop counter for
+ * packet-ins from a switch, the counterHierarchy
+ * can be "00:00:00:00:01:02:03:04/pktin/drops"
+ * It is necessary that counters in hierarchical levels
+ * above have already been pre-registered - in this
+ * example: "00:00:00:00:01:02:03:04/pktin" and
+ * "00:00:00:00:01:02:03:04"
+ * @param counterDescription a descriptive string that gives more information
+ * of what the counter is measuring. For example,
+ * "Measures the number of incoming packets seen by
+ * this module".
+ * @param counterType One of CounterType. On-demand counter types
+ * need to be explicitly enabled/disabled using other
+ * methods in this API -- i.e. registering them is
+ * not enough to start counting.
+ * @param metaData variable arguments that qualify a counter
+ * eg. warn, error etc.
+ * @return IDebugCounter with update methods that can be
+ * used to update a counter.
+ * @throws MaxCountersRegistered
+ * @throws MaxHierarchyRegistered
+ * @throws MissingHierarchicalLevel
+ */
+ public IDebugCounter registerCounter(String moduleName, String counterHierarchy,
+ String counterDescription, CounterType counterType,
+ String... metaData)
+ throws CounterException;
+
+ /**
+ * Flush all thread-local counter values (from the current thread)
+ * to the global counter store. This method is not intended for use by any
+ * module. It's typical usage is from core and it is meant
+ * to flush those counters that are updated in the packet-processing pipeline,
+ * typically with the 'updateCounterNoFlush" methods in IDebugCounter.
+ */
+ public void flushCounters();
+
+ /**
+ * Resets the value of counters in the hierarchy to zero. Note that the reset
+ * applies to the level of counter hierarchy specified AND ALL LEVELS BELOW it
+ * in the hierarchy.
+ * For example: If a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops"
+ * specifying a reset hierarchy: "00:00:00:00:01:02:03:04"
+ * will reset all counters for the switch dpid specified;
+ * while specifying a reset hierarchy: ""00:00:00:00:01:02:03:04/pktin"
+ * will reset the pktin counter and all levels below it (like drops)
+ * for the switch dpid specified.
+ */
+ void resetCounterHierarchy(String moduleName, String counterHierarchy);
+
+ /**
+ * Resets the values of all counters in the system.
+ */
+ public void resetAllCounters();
+
+ /**
+ * Resets the values of all counters belonging
+ * to a module with the given 'moduleName'.
+ */
+ public void resetAllModuleCounters(String moduleName);
+
+ /**
+ * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
+ * enable counting on the counter. Note that this step is necessary to start
+ * counting for these counter types - merely registering the counter is not
+ * enough (as is the case for CounterType.ALWAYS_COUNT). Newly
+ * enabled counters start from an initial value of zero.
+ *
+ * Enabling a counter in a counterHierarchy enables only THAT counter. It
+ * does not enable any other part of the counterHierarchy. For example, if
+ * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the
+ * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then enabling
+ * the 'pktin' counter by specifying the counterHierarchy as
+ * "00:00:00:00:01:02:03:04/pktin" does NOT enable the 'drops' counter.
+ */
+ public void enableCtrOnDemand(String moduleName, String counterHierarchy);
+
+ /**
+ * This method applies only to CounterType.COUNT_ON_DEMAND. It is used to
+ * enable counting on the counter. Note that disabling a counter results in a loss
+ * of the counter value. When re-enabled the counter will restart from zero.
+ *
+ * Disabling a counter in a counterHierarchy disables only THAT counter. It
+ * does not disable any other part of the counterHierarchy. For example, if
+ * a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", where the
+ * 'pktin' and 'drops' counters are CounterType.COUNT_ON_DEMAND, then disabling
+ * the 'pktin' counter by specifying the counterHierarchy as
+ * "00:00:00:00:01:02:03:04/pktin" does NOT disable the 'drops' counter.
+ */
+ public void disableCtrOnDemand(String moduleName, String counterHierarchy);
+
+ /**
+ * Get counter value and associated information for the specified counterHierarchy.
+ * Note that information on the level of counter hierarchy specified
+ * AND ALL LEVELS BELOW it in the hierarchy will be returned.
+ *
+ * For example,
+ * if a hierarchy exists like "00:00:00:00:01:02:03:04/pktin/drops", then
+ * specifying a counterHierarchy of "00:00:00:00:01:02:03:04/pktin" in the
+ * get call will return information on the 'pktin' as well as the 'drops'
+ * counters for the switch dpid specified.
+ *
+ * @return A list of DebugCounterInfo or an empty list if the counter
+ * could not be found
+ */
+ public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
+ String counterHierarchy);
+
+ /**
+ * Get counter values and associated information for all counters in the
+ * system.
+ *
+ * @return the list of values/info or an empty list
+ */
+ public List<DebugCounterInfo> getAllCounterValues();
+
+ /**
+ * Get counter values and associated information for all counters associated
+ * with a module.
+ *
+ * @param moduleName
+ * @return the list of values/info or an empty list
+ */
+ public List<DebugCounterInfo> getModuleCounterValues(String moduleName);
+
+ /**
+ * Convenience method to figure out if the the given 'counterHierarchy' corresponds
+ * to a registered counterHierarchy for 'moduleName'. Note that the counter may or
+ * may not be enabled for counting, but if it is registered the method will
+ * return true.
+ *
+ * @param param
+ * @return false if moduleCounterHierarchy is not a registered counter
+ */
+ public boolean containsModuleCounterHierarchy(String moduleName,
+ String counterHierarchy);
+
+ /**
+ * Convenience method to figure out if the the given 'moduleName' corresponds
+ * to a registered moduleName or not. Note that the module may or may not have
+ * a counter enabled for counting, but if it is registered the method will
+ * return true.
+ *
+ * @param param
+ * @return false if moduleName is not a registered counter
+ */
+ public boolean containsModuleName(String moduleName);
+
+ /**
+ * Returns a list of moduleNames registered for debug counters or an empty
+ * list if no counters have been registered in the system.
+ */
+ public List<String> getModuleList();
+
+ /**
+ * Returns a list of all counters registered for a specific moduleName
+ * or a empty list.
+ */
+ public List<String> getModuleCounterList(String moduleName);
+
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/NullDebugCounter.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/NullDebugCounter.java
new file mode 100644
index 0000000..1775c50
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/debugcounter/NullDebugCounter.java
@@ -0,0 +1,116 @@
+package net.onrc.onos.of.ctl.debugcounter;
+
+import java.util.Collections;
+import java.util.List;
+
+import net.onrc.onos.of.ctl.debugcounter.DebugCounter.DebugCounterInfo;
+
+public class NullDebugCounter implements IDebugCounterService {
+
+ @Override
+ public void flushCounters() {
+
+ }
+
+ @Override
+ public void resetAllCounters() {
+
+ }
+
+ @Override
+ public void resetAllModuleCounters(String moduleName) {
+
+ }
+
+
+ @Override
+ public void resetCounterHierarchy(String moduleName, String counterHierarchy) {
+
+ }
+
+ @Override
+ public void enableCtrOnDemand(String moduleName, String counterHierarchy) {
+
+ }
+
+ @Override
+ public void disableCtrOnDemand(String moduleName, String counterHierarchy) {
+
+ }
+
+ @Override
+ public List<DebugCounterInfo> getCounterHierarchy(String moduleName,
+ String counterHierarchy) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<DebugCounterInfo> getAllCounterValues() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<DebugCounterInfo> getModuleCounterValues(String moduleName) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean containsModuleCounterHierarchy(String moduleName,
+ String counterHierarchy) {
+ return false;
+ }
+
+ @Override
+ public boolean containsModuleName(String moduleName) {
+ return false;
+ }
+
+ @Override
+ public
+ IDebugCounter
+ registerCounter(String moduleName, String counterHierarchy,
+ String counterDescription,
+ CounterType counterType, String... metaData)
+ throws MaxCountersRegistered {
+ return new NullCounterImpl();
+ }
+
+ @Override
+ public List<String> getModuleList() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List<String> getModuleCounterList(String moduleName) {
+ return Collections.emptyList();
+ }
+
+ public static class NullCounterImpl implements IDebugCounter {
+
+ @Override
+ public void updateCounterWithFlush() {
+
+ }
+
+ @Override
+ public void updateCounterNoFlush() {
+
+ }
+
+ @Override
+ public void updateCounterWithFlush(int incr) {
+ }
+
+ @Override
+ public void updateCounterNoFlush(int incr) {
+
+ }
+
+ @Override
+ public long getCounterValue() {
+ return -1;
+ }
+
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/Controller.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/Controller.java
new file mode 100644
index 0000000..84f090a
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/Controller.java
@@ -0,0 +1,839 @@
+/**
+ * Copyright 2011, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.internal;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+
+import net.onrc.onos.of.ctl.IOFSwitchManager;
+import net.onrc.onos.of.ctl.Role;
+import net.onrc.onos.of.ctl.annotations.LogMessageDoc;
+import net.onrc.onos.of.ctl.annotations.LogMessageDocs;
+import net.onrc.onos.of.ctl.debugcounter.DebugCounter;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounter;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterException;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterType;
+import net.onrc.onos.of.ctl.internal.OFChannelHandler.RoleRecvStatus;
+import net.onrc.onos.of.ctl.registry.IControllerRegistry;
+import net.onrc.onos.of.ctl.registry.RegistryException;
+import net.onrc.onos.of.ctl.registry.IControllerRegistry.ControlChangeCallback;
+import net.onrc.onos.of.ctl.util.Dpid;
+import net.onrc.onos.of.ctl.util.DummySwitchForTesting;
+import net.onrc.onos.of.ctl.util.InstanceId;
+import net.onrc.onos.of.ctl.IOFSwitch;
+import net.onrc.onos.of.ctl.IOFSwitch.PortChangeType;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.jboss.netty.bootstrap.ServerBootstrap;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.group.ChannelGroup;
+import org.jboss.netty.channel.group.DefaultChannelGroup;
+import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * The main controller class. Handles all setup and network listeners
+ * - Distributed ownership control of switch through IControllerRegistryService
+ */
+@Component(immediate = true)
+public class Controller {
+
+ protected static final Logger log = LoggerFactory.getLogger(Controller.class);
+ static final String ERROR_DATABASE =
+ "The controller could not communicate with the system database.";
+ protected static final OFFactory FACTORY13 = OFFactories.getFactory(OFVersion.OF_13);
+ protected static final OFFactory FACTORY10 = OFFactories.getFactory(OFVersion.OF_10);
+
+ // connectedSwitches cache contains all connected switch's channelHandlers
+ // including ones where this controller is a master/equal/slave controller
+ // as well as ones that have not been activated yet
+ protected ConcurrentHashMap<Long, OFChannelHandler> connectedSwitches;
+ // These caches contains only those switches that are active
+ protected ConcurrentHashMap<Long, IOFSwitch> activeMasterSwitches;
+ protected ConcurrentHashMap<Long, IOFSwitch> activeEqualSwitches;
+ // lock to synchronize on, when manipulating multiple caches above
+ private Object multiCacheLock;
+
+ // The controllerNodeIPsCache maps Controller IDs to their IP address.
+ // It's only used by handleControllerNodeIPsChanged
+ protected HashMap<String, String> controllerNodeIPsCache;
+
+ // Module dependencies
+
+ protected IControllerRegistry registryService;
+ protected IDebugCounterService debugCounters;
+
+
+ private IOFSwitchManager switchManager;
+
+ // Configuration options
+ protected int openFlowPort = 6633;
+ protected int workerThreads = 0;
+
+ // defined counters
+ private Counters counters;
+
+ // Start time of the controller
+ protected long systemStartTime;
+
+ // Flag to always flush flow table on switch reconnect (HA or otherwise)
+ protected boolean alwaysClearFlowsOnSwAdd = false;
+ private InstanceId instanceId;
+
+ // Perf. related configuration
+ protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
+ protected static final int BATCH_MAX_SIZE = 100;
+ protected static final boolean ALWAYS_DECODE_ETH = true;
+
+ protected boolean addConnectedSwitch(long dpid, OFChannelHandler h) {
+ if (connectedSwitches.get(dpid) != null) {
+ log.error("Trying to add connectedSwitch but found a previous "
+ + "value for dpid: {}", dpid);
+ return false;
+ } else {
+ log.error("Added switch {}", dpid);
+ connectedSwitches.put(dpid, h);
+ return true;
+ }
+ }
+
+ private boolean validActivation(long dpid) {
+ if (connectedSwitches.get(dpid) == null) {
+ log.error("Trying to activate switch but is not in "
+ + "connected switches: dpid {}. Aborting ..",
+ HexString.toHexString(dpid));
+ return false;
+ }
+ if (activeMasterSwitches.get(dpid) != null ||
+ activeEqualSwitches.get(dpid) != null) {
+ log.error("Trying to activate switch but it is already "
+ + "activated: dpid {}. Found in activeMaster: {} "
+ + "Found in activeEqual: {}. Aborting ..", new Object[] {
+ HexString.toHexString(dpid),
+ (activeMasterSwitches.get(dpid) == null) ? 'N' : 'Y',
+ (activeEqualSwitches.get(dpid) == null) ? 'N' : 'Y'});
+ counters.switchWithSameDpidActivated.updateCounterWithFlush();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Called when a switch is activated, with this controller's role as MASTER.
+ */
+ protected boolean addActivatedMasterSwitch(long dpid, IOFSwitch sw) {
+ synchronized (multiCacheLock) {
+ if (!validActivation(dpid)) {
+ return false;
+ }
+ activeMasterSwitches.put(dpid, sw);
+ }
+ //update counters and events
+ counters.switchActivated.updateCounterWithFlush();
+
+ return true;
+ }
+
+ /**
+ * Called when a switch is activated, with this controller's role as EQUAL.
+ */
+ protected boolean addActivatedEqualSwitch(long dpid, IOFSwitch sw) {
+ synchronized (multiCacheLock) {
+ if (!validActivation(dpid)) {
+ return false;
+ }
+ activeEqualSwitches.put(dpid, sw);
+ }
+ //update counters and events
+ counters.switchActivated.updateCounterWithFlush();
+ return true;
+ }
+
+ /**
+ * Called when this controller's role for a switch transitions from equal
+ * to master. For 1.0 switches, we internally refer to the role 'slave' as
+ * 'equal' - so this transition is equivalent to 'addActivatedMasterSwitch'.
+ */
+ protected void transitionToMasterSwitch(long dpid) {
+ synchronized (multiCacheLock) {
+ IOFSwitch sw = activeEqualSwitches.remove(dpid);
+ if (sw == null) {
+ log.error("Transition to master called on sw {}, but switch "
+ + "was not found in controller-cache", dpid);
+ return;
+ }
+ activeMasterSwitches.put(dpid, sw);
+ }
+ }
+
+
+ /**
+ * Called when this controller's role for a switch transitions to equal.
+ * For 1.0 switches, we internally refer to the role 'slave' as
+ * 'equal'.
+ */
+ protected void transitionToEqualSwitch(long dpid) {
+ synchronized (multiCacheLock) {
+ IOFSwitch sw = activeMasterSwitches.remove(dpid);
+ if (sw == null) {
+ log.error("Transition to equal called on sw {}, but switch "
+ + "was not found in controller-cache", dpid);
+ return;
+ }
+ activeEqualSwitches.put(dpid, sw);
+ }
+
+ }
+
+ /**
+ * Clear all state in controller switch maps for a switch that has
+ * disconnected from the local controller. Also release control for
+ * that switch from the global repository. Notify switch listeners.
+ */
+ protected void removeConnectedSwitch(long dpid) {
+ releaseRegistryControl(dpid);
+ connectedSwitches.remove(dpid);
+ IOFSwitch sw = activeMasterSwitches.remove(dpid);
+ if (sw == null) {
+ sw = activeEqualSwitches.remove(dpid);
+ }
+ if (sw != null) {
+ sw.cancelAllStatisticsReplies();
+ sw.setConnected(false); // do we need this?
+ }
+ counters.switchDisconnected.updateCounterWithFlush();
+
+ }
+
+ /**
+ * Indicates that ports on the given switch have changed. Enqueue a
+ * switch update.
+ * @param sw
+ */
+ protected void notifyPortChanged(long dpid, OFPortDesc port,
+ PortChangeType changeType) {
+ if (port == null || changeType == null) {
+ String msg = String.format("Switch port or changetType must not "
+ + "be null in port change notification");
+ throw new NullPointerException(msg);
+ }
+ if (connectedSwitches.get(dpid) == null || getSwitch(dpid) == null) {
+ log.warn("Port change update on switch {} not connected or activated "
+ + "... Aborting.", HexString.toHexString(dpid));
+ return;
+ }
+
+ }
+
+ // ***************
+ // Getters/Setters
+ // ***************
+
+
+ public synchronized void setIOFSwitchManager(IOFSwitchManager swManager) {
+ this.switchManager = swManager;
+ this.registryService = swManager.getRegistry();
+ }
+
+
+ public void setDebugCounter(IDebugCounterService dcs) {
+ this.debugCounters = dcs;
+ }
+
+ IDebugCounterService getDebugCounter() {
+ return this.debugCounters;
+ }
+
+ // **********************
+ // Role Handling
+ // **********************
+
+ /**
+ * created by ONOS - works with registry service.
+ */
+ protected class RoleChangeCallback implements ControlChangeCallback {
+ @Override
+ public void controlChanged(long dpidLong, boolean hasControl) {
+ Dpid dpid = new Dpid(dpidLong);
+ log.info("Role change callback for switch {}, hasControl {}",
+ dpid, hasControl);
+
+ Role role = null;
+
+ /*
+ * issue #229
+ * Cannot rely on sw.getRole() as it can be behind due to pending
+ * role changes in the queue. Just submit it and late the
+ * RoleChanger handle duplicates.
+ */
+
+ if (hasControl) {
+ role = Role.MASTER;
+ } else {
+ role = Role.EQUAL; // treat the same as Role.SLAVE
+ }
+
+ OFChannelHandler swCh = connectedSwitches.get(dpid.value());
+ if (swCh == null) {
+ log.warn("Switch {} not found in connected switches", dpid);
+ return;
+ }
+
+ log.debug("Sending role request {} msg to {}", role, dpid);
+ swCh.sendRoleRequest(role, RoleRecvStatus.MATCHED_SET_ROLE);
+ }
+ }
+
+ /**
+ * Submit request to the registry service for mastership of the
+ * switch.
+ * @param dpid this datapath to get role for
+ */
+ public synchronized void submitRegistryRequest(long dpid) {
+ if (registryService == null) {
+ /*
+ * If we have no registry then simply assign
+ * mastership to this controller.
+ */
+ new RoleChangeCallback().controlChanged(dpid, true);
+ return;
+ }
+ OFChannelHandler h = connectedSwitches.get(dpid);
+ if (h == null) {
+ log.error("Trying to request registry control for switch {} "
+ + "not in connected switches. Aborting.. ",
+ HexString.toHexString(dpid));
+ connectedSwitches.get(dpid).disconnectSwitch();
+ return;
+ }
+ //Request control of the switch from the global registry
+ try {
+ h.controlRequested = Boolean.TRUE;
+ registryService.requestControl(dpid, new RoleChangeCallback());
+ } catch (RegistryException e) {
+ log.debug("Registry error: {}", e.getMessage());
+ h.controlRequested = Boolean.FALSE;
+ }
+ if (!h.controlRequested) { // XXX what is being attempted here?
+ // yield to allow other thread(s) to release control
+ // TODO AAS: this is awful and needs to be fixed
+ Thread.yield();
+ // safer to bounce the switch to reconnect here than proceeding further
+ // XXX S why? can't we just try again a little later?
+ log.debug("Closing sw:{} because we weren't able to request control " +
+ "successfully" + dpid);
+ connectedSwitches.get(dpid).disconnectSwitch();
+ }
+ }
+
+ /**
+ * Relinquish role for the switch.
+ * @param dpidLong the controlled datapath
+ */
+ public synchronized void releaseRegistryControl(long dpidLong) {
+ OFChannelHandler h = connectedSwitches.get(dpidLong);
+ if (h == null) {
+ log.error("Trying to release registry control for switch {} "
+ + "not in connected switches. Aborting.. ",
+ HexString.toHexString(dpidLong));
+ return;
+ }
+ if (registryService != null && h.controlRequested) {
+ //TODO the above is not good for testing need to change controlrequest to method call.
+ registryService.releaseControl(dpidLong);
+ }
+ }
+
+
+ // FIXME: remove this method
+ public Map<Long, IOFSwitch> getSwitches() {
+ return getMasterSwitches();
+ }
+
+ // FIXME: remove this method
+ public Map<Long, IOFSwitch> getMasterSwitches() {
+ return Collections.unmodifiableMap(activeMasterSwitches);
+ }
+
+
+
+ public Set<Long> getAllSwitchDpids() {
+ Set<Long> dpids = new HashSet<Long>();
+ dpids.addAll(activeMasterSwitches.keySet());
+ dpids.addAll(activeEqualSwitches.keySet());
+ return dpids;
+ }
+
+
+ public Set<Long> getAllMasterSwitchDpids() {
+ Set<Long> dpids = new HashSet<Long>();
+ dpids.addAll(activeMasterSwitches.keySet());
+ return dpids;
+ }
+
+
+ public Set<Long> getAllEqualSwitchDpids() {
+ Set<Long> dpids = new HashSet<Long>();
+ dpids.addAll(activeEqualSwitches.keySet());
+ return dpids;
+ }
+
+
+ public IOFSwitch getSwitch(long dpid) {
+ IOFSwitch sw = null;
+ sw = activeMasterSwitches.get(dpid);
+ if (sw != null) {
+ return sw;
+ }
+ sw = activeEqualSwitches.get(dpid);
+ if (sw != null) {
+ return sw;
+ }
+ return sw;
+ }
+
+
+ public IOFSwitch getMasterSwitch(long dpid) {
+ return activeMasterSwitches.get(dpid);
+ }
+
+
+ public IOFSwitch getEqualSwitch(long dpid) {
+ return activeEqualSwitches.get(dpid);
+ }
+
+
+
+
+
+ public OFFactory getOFMessageFactory10() {
+ return FACTORY10;
+ }
+
+
+ public OFFactory getOFMessageFactory13() {
+ return FACTORY13;
+ }
+
+
+
+ public Map<String, String> getControllerNodeIPs() {
+ // We return a copy of the mapping so we can guarantee that
+ // the mapping return is the same as one that will be (or was)
+ // dispatched to IHAListeners
+ HashMap<String, String> retval = new HashMap<String, String>();
+ synchronized (controllerNodeIPsCache) {
+ retval.putAll(controllerNodeIPsCache);
+ }
+ return retval;
+ }
+
+
+ public long getSystemStartTime() {
+ return (this.systemStartTime);
+ }
+
+
+ public InstanceId getInstanceId() {
+ return instanceId;
+ }
+
+
+ // **************
+ // Initialization
+ // **************
+
+ /**
+ * Tell controller that we're ready to accept switches loop.
+ *
+ * @throws IOException
+ */
+ @LogMessageDocs({
+ @LogMessageDoc(message = "Listening for switch connections on {address}",
+ explanation = "The controller is ready and listening for new" +
+ " switch connections"),
+ @LogMessageDoc(message = "Storage exception in controller " +
+ "updates loop; terminating process",
+ explanation = ERROR_DATABASE,
+ recommendation = LogMessageDoc.CHECK_CONTROLLER),
+ @LogMessageDoc(level = "ERROR",
+ message = "Exception in controller updates loop",
+ explanation = "Failed to dispatch controller event",
+ recommendation = LogMessageDoc.GENERIC_ACTION)
+ })
+ public void run() {
+
+ try {
+ final ServerBootstrap bootstrap = createServerBootStrap();
+
+ bootstrap.setOption("reuseAddr", true);
+ bootstrap.setOption("child.keepAlive", true);
+ bootstrap.setOption("child.tcpNoDelay", true);
+ bootstrap.setOption("child.sendBufferSize", Controller.SEND_BUFFER_SIZE);
+
+ ChannelPipelineFactory pfact =
+ new OpenflowPipelineFactory(this, null);
+ bootstrap.setPipelineFactory(pfact);
+ InetSocketAddress sa = new InetSocketAddress(openFlowPort);
+ final ChannelGroup cg = new DefaultChannelGroup();
+ cg.add(bootstrap.bind(sa));
+
+ log.info("Listening for switch connections on {}", sa);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ 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));
+ }
+ }
+
+ public void setConfigParams(Map<String, String> configParams) {
+ String ofPort = configParams.get("openflowport");
+ if (ofPort != null) {
+ this.openFlowPort = Integer.parseInt(ofPort);
+ }
+ log.debug("OpenFlow port set to {}", this.openFlowPort);
+ String threads = configParams.get("workerthreads");
+ if (threads != null) {
+ this.workerThreads = Integer.parseInt(threads);
+ }
+ log.debug("Number of worker threads set to {}", this.workerThreads);
+ String controllerId = configParams.get("controllerid");
+ if (controllerId != null) {
+ this.instanceId = new InstanceId(controllerId);
+ } else {
+ //Try to get the hostname of the machine and use that for controller ID
+ try {
+ String hostname = java.net.InetAddress.getLocalHost().getHostName();
+ this.instanceId = new InstanceId(hostname);
+ } catch (UnknownHostException e) {
+ log.warn("Can't get hostname, using the default");
+ }
+ }
+
+ log.debug("ControllerId set to {}", this.instanceId);
+ }
+
+
+ /**
+ * Initialize internal data structures.
+ */
+ public void init(Map<String, String> configParams) {
+ // These data structures are initialized here because other
+ // module's startUp() might be called before ours
+ this.activeMasterSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
+ this.activeEqualSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
+ this.connectedSwitches = new ConcurrentHashMap<Long, OFChannelHandler>();
+ this.controllerNodeIPsCache = new HashMap<String, String>();
+
+ setConfigParams(configParams);
+ this.systemStartTime = System.currentTimeMillis();
+ this.setDebugCounter(new DebugCounter());
+ this.counters = new Counters();
+ this.multiCacheLock = new Object();
+
+ }
+
+ /**
+ * Startup all of the controller's components.
+ */
+ @LogMessageDoc(message = "Waiting for storage source",
+ explanation = "The system database is not yet ready",
+ recommendation = "If this message persists, this indicates " +
+ "that the system database has failed to start. " +
+ LogMessageDoc.CHECK_CONTROLLER)
+ public synchronized void startupComponents() {
+ try {
+ if (registryService != null) {
+ registryService.registerController(instanceId.toString());
+ }
+ } catch (RegistryException e) {
+ log.warn("Registry service error: {}", e.getMessage());
+ }
+
+ // register counters and events
+ try {
+ this.counters.createCounters(debugCounters);
+ } catch (CounterException e) {
+ log.warn("Counters unavailable: {}", e.getMessage());
+ }
+ }
+
+ // **************
+ // debugCounter registrations
+ // **************
+
+ public static class Counters {
+ public static final String PREFIX = "controller";
+ public IDebugCounter switchActivated;
+ public IDebugCounter switchWithSameDpidActivated; // warn
+ public IDebugCounter switchDisconnected;
+ public IDebugCounter messageReceived;
+ public IDebugCounter switchDisconnectReadTimeout;
+ public IDebugCounter switchDisconnectHandshakeTimeout;
+ public IDebugCounter switchDisconnectIOError;
+ public IDebugCounter switchDisconnectParseError;
+ public IDebugCounter switchDisconnectSwitchStateException;
+ public IDebugCounter rejectedExecutionException;
+ public IDebugCounter switchDisconnectOtherException;
+ public IDebugCounter switchConnected;
+ public IDebugCounter unhandledMessage;
+ public IDebugCounter packetInWhileSwitchIsSlave;
+ public IDebugCounter epermErrorWhileSwitchIsMaster;
+ public IDebugCounter roleReplyTimeout;
+ public IDebugCounter roleReplyReceived; // expected RoleReply received
+ public IDebugCounter roleReplyErrorUnsupported;
+ public IDebugCounter switchCounterRegistrationFailed;
+
+ void createCounters(IDebugCounterService debugCounters) throws CounterException {
+
+ switchActivated =
+ debugCounters.registerCounter(
+ PREFIX, "switch-activated",
+ "A switch connected to this controller is now " +
+ "in MASTER role",
+ CounterType.ALWAYS_COUNT);
+
+ switchWithSameDpidActivated = // warn
+ debugCounters.registerCounter(
+ PREFIX, "switch-with-same-dpid-activated",
+ "A switch with the same DPID as another switch " +
+ "connected to the controller. This can be " +
+ "caused by multiple switches configured with " +
+ "the same DPID or by a switch reconnecting very " +
+ "quickly.",
+ CounterType.COUNT_ON_DEMAND,
+ IDebugCounterService.CTR_MDATA_WARN);
+
+ switchDisconnected =
+ debugCounters.registerCounter(
+ PREFIX, "switch-disconnected",
+ "FIXME: switch has disconnected",
+ CounterType.ALWAYS_COUNT);
+
+ //------------------------
+ // channel handler counters. Factor them out ??
+ messageReceived =
+ debugCounters.registerCounter(
+ PREFIX, "message-received",
+ "Number of OpenFlow messages received. Some of " +
+ "these might be throttled",
+ CounterType.ALWAYS_COUNT);
+
+ switchDisconnectReadTimeout =
+ debugCounters.registerCounter(
+ PREFIX, "switch-disconnect-read-timeout",
+ "Number of times a switch was disconnected due " +
+ "due the switch failing to send OpenFlow " +
+ "messages or responding to OpenFlow ECHOs",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_ERROR);
+ switchDisconnectHandshakeTimeout =
+ debugCounters.registerCounter(
+ PREFIX, "switch-disconnect-handshake-timeout",
+ "Number of times a switch was disconnected " +
+ "because it failed to complete the handshake " +
+ "in time.",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_ERROR);
+ switchDisconnectIOError =
+ debugCounters.registerCounter(
+ PREFIX, "switch-disconnect-io-error",
+ "Number of times a switch was disconnected " +
+ "due to IO errors on the switch connection.",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_ERROR);
+ switchDisconnectParseError =
+ debugCounters.registerCounter(
+ PREFIX, "switch-disconnect-parse-error",
+ "Number of times a switch was disconnected " +
+ "because it sent an invalid packet that could " +
+ "not be parsed",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_ERROR);
+
+ switchDisconnectSwitchStateException =
+ debugCounters.registerCounter(
+ PREFIX, "switch-disconnect-switch-state-exception",
+ "Number of times a switch was disconnected " +
+ "because it sent messages that were invalid " +
+ "given the switch connection's state.",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_ERROR);
+ rejectedExecutionException =
+ debugCounters.registerCounter(
+ PREFIX, "rejected-execution-exception",
+ "TODO",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_ERROR);
+
+ switchDisconnectOtherException =
+ debugCounters.registerCounter(
+ PREFIX, "switch-disconnect-other-exception",
+ "Number of times a switch was disconnected " +
+ "due to an exceptional situation not covered " +
+ "by other counters",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_ERROR);
+
+ switchConnected =
+ debugCounters.registerCounter(
+ PREFIX, "switch-connected",
+ "Number of times a new switch connection was " +
+ "established",
+ CounterType.ALWAYS_COUNT);
+
+ unhandledMessage =
+ debugCounters.registerCounter(
+ PREFIX, "unhandled-message",
+ "Number of times an OpenFlow message was " +
+ "received that the controller ignored because " +
+ "it was inapproriate given the switch " +
+ "connection's state.",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_WARN);
+ // might be less than warning
+
+ packetInWhileSwitchIsSlave =
+ debugCounters.registerCounter(
+ PREFIX, "packet-in-while-switch-is-slave",
+ "Number of times a packet in was received " +
+ "from a switch that was in SLAVE role. " +
+ "Possibly inidicates inconsistent roles.",
+ CounterType.ALWAYS_COUNT);
+ epermErrorWhileSwitchIsMaster =
+ debugCounters.registerCounter(
+ PREFIX, "eperm-error-while-switch-is-master",
+ "Number of times a permission error was " +
+ "received while the switch was in MASTER role. " +
+ "Possibly inidicates inconsistent roles.",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_WARN);
+
+ roleReplyTimeout =
+ debugCounters.registerCounter(
+ PREFIX, "role-reply-timeout",
+ "Number of times a role request message did not " +
+ "receive the expected reply from a switch",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_WARN);
+
+ roleReplyReceived = // expected RoleReply received
+ debugCounters.registerCounter(
+ PREFIX, "role-reply-received",
+ "Number of times the controller received the " +
+ "expected role reply message from a switch",
+ CounterType.ALWAYS_COUNT);
+
+ roleReplyErrorUnsupported =
+ debugCounters.registerCounter(
+ PREFIX, "role-reply-error-unsupported",
+ "Number of times the controller received an " +
+ "error from a switch in response to a role " +
+ "request indicating that the switch does not " +
+ "support roles.",
+ CounterType.ALWAYS_COUNT);
+
+ switchCounterRegistrationFailed =
+ debugCounters.registerCounter(PREFIX,
+ "switch-counter-registration-failed",
+ "Number of times the controller failed to " +
+ "register per-switch debug counters",
+ CounterType.ALWAYS_COUNT,
+ IDebugCounterService.CTR_MDATA_WARN);
+
+
+ }
+ }
+
+ public Counters getCounters() {
+ return this.counters;
+ }
+
+
+ // **************
+ // Utility methods
+ // **************
+
+ public Map<String, Long> getMemory() {
+ Map<String, Long> m = new HashMap<String, Long>();
+ Runtime runtime = Runtime.getRuntime();
+ m.put("total", runtime.totalMemory());
+ m.put("free", runtime.freeMemory());
+ return m;
+ }
+
+
+ public Long getUptime() {
+ RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
+ return rb.getUptime();
+ }
+
+ /**
+ * Forward to the driver-manager to get an IOFSwitch instance.
+ * @param desc
+ * @return
+ */
+ protected IOFSwitch getOFSwitchInstance(OFDescStatsReply desc, OFVersion ofv) {
+ if (switchManager == null) {
+ return new DummySwitchForTesting();
+ }
+ return switchManager.getSwitchImpl(desc.getMfrDesc(), desc.getHwDesc(),
+ desc.getSwDesc(), ofv);
+ }
+
+ @Activate
+ public void activate() {
+ log.info("Initialising OpenFlow Lib and IO");
+ this.init(new HashMap<String, String>());
+ this.startupComponents();
+ this.run();
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/HandshakeTimeoutException.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/HandshakeTimeoutException.java
new file mode 100644
index 0000000..48856a9
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/HandshakeTimeoutException.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright 2011, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.internal;
+
+/**
+ * Exception is thrown when the handshake fails to complete.
+ * before a specified time
+ *
+ */
+public class HandshakeTimeoutException extends Exception {
+
+ private static final long serialVersionUID = 6859880268940337312L;
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/HandshakeTimeoutHandler.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/HandshakeTimeoutHandler.java
new file mode 100644
index 0000000..2ed3fd2
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/HandshakeTimeoutHandler.java
@@ -0,0 +1,94 @@
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson, Stanford University
+*
+* Licensed under the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License. You may obtain
+* a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+**/
+
+package net.onrc.onos.of.ctl.internal;
+
+import java.util.concurrent.TimeUnit;
+
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.Timer;
+import org.jboss.netty.util.TimerTask;
+
+/**
+ * Trigger a timeout if a switch fails to complete handshake soon enough.
+ */
+public class HandshakeTimeoutHandler
+ extends SimpleChannelUpstreamHandler {
+ static final HandshakeTimeoutException EXCEPTION =
+ new HandshakeTimeoutException();
+
+ final OFChannelHandler channelHandler;
+ final Timer timer;
+ final long timeoutNanos;
+ volatile Timeout timeout;
+
+ public HandshakeTimeoutHandler(OFChannelHandler channelHandler,
+ Timer timer,
+ long timeoutSeconds) {
+ super();
+ this.channelHandler = channelHandler;
+ this.timer = timer;
+ this.timeoutNanos = TimeUnit.SECONDS.toNanos(timeoutSeconds);
+
+ }
+
+ @Override
+ public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
+ throws Exception {
+ if (timeoutNanos > 0) {
+ timeout = timer.newTimeout(new HandshakeTimeoutTask(ctx),
+ timeoutNanos, TimeUnit.NANOSECONDS);
+ }
+ ctx.sendUpstream(e);
+ }
+
+ @Override
+ public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
+ throws Exception {
+ if (timeout != null) {
+ timeout.cancel();
+ timeout = null;
+ }
+ }
+
+ private final class HandshakeTimeoutTask implements TimerTask {
+
+ private final ChannelHandlerContext ctx;
+
+ HandshakeTimeoutTask(ChannelHandlerContext ctx) {
+ this.ctx = ctx;
+ }
+
+ @Override
+ public void run(Timeout t) throws Exception {
+ if (t.isCancelled()) {
+ return;
+ }
+
+ if (!ctx.getChannel().isOpen()) {
+ return;
+ }
+ if (!channelHandler.isHandshakeComplete()) {
+ Channels.fireExceptionCaught(ctx, EXCEPTION);
+ }
+ }
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFChannelHandler.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFChannelHandler.java
new file mode 100644
index 0000000..3b18a59
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFChannelHandler.java
@@ -0,0 +1,2153 @@
+package net.onrc.onos.of.ctl.internal;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.RejectedExecutionException;
+
+import net.onrc.onos.of.ctl.IOFSwitch;
+import net.onrc.onos.of.ctl.IOFSwitch.PortChangeEvent;
+import net.onrc.onos.of.ctl.Role;
+import net.onrc.onos.of.ctl.annotations.LogMessageDoc;
+import net.onrc.onos.of.ctl.annotations.LogMessageDocs;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterException;
+import net.onrc.onos.of.ctl.internal.Controller.Counters;
+import net.onrc.onos.of.ctl.internal.OFChannelHandler.ChannelState.RoleReplyInfo;
+
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
+import org.jboss.netty.handler.timeout.IdleStateEvent;
+import org.jboss.netty.handler.timeout.ReadTimeoutException;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
+import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
+import org.projectfloodlight.openflow.protocol.OFBarrierReply;
+import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
+import org.projectfloodlight.openflow.protocol.OFControllerRole;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFDescStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFEchoReply;
+import org.projectfloodlight.openflow.protocol.OFEchoRequest;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFErrorType;
+import org.projectfloodlight.openflow.protocol.OFExperimenter;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFFlowModFailedCode;
+import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
+import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
+import org.projectfloodlight.openflow.protocol.OFGetConfigRequest;
+import org.projectfloodlight.openflow.protocol.OFHello;
+import org.projectfloodlight.openflow.protocol.OFHelloElem;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRoleReply;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
+import org.projectfloodlight.openflow.protocol.OFQueueGetConfigReply;
+import org.projectfloodlight.openflow.protocol.OFRoleReply;
+import org.projectfloodlight.openflow.protocol.OFRoleRequest;
+import org.projectfloodlight.openflow.protocol.OFSetConfig;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
+import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
+import org.projectfloodlight.openflow.protocol.errormsg.OFRoleRequestFailedErrorMsg;
+import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ * Channel handler deals with the switch connection and dispatches
+ * switch messages to the appropriate locations.
+ */
+class OFChannelHandler extends IdleStateAwareChannelHandler {
+ private static final Logger log = LoggerFactory.getLogger(OFChannelHandler.class);
+ private static final long DEFAULT_ROLE_TIMEOUT_MS = 2 * 1000; // 10 sec
+ private final Controller controller;
+ private final Counters counters;
+ private IOFSwitch sw;
+ private long thisdpid; // channelHandler cached value of connected switch id
+ private Channel channel;
+ // State needs to be volatile because the HandshakeTimeoutHandler
+ // needs to check if the handshake is complete
+ private volatile ChannelState state;
+
+ // All role messaging is handled by the roleChanger. The channel state machine
+ // coordinates between the roleChanger and the controller-global-registry-service
+ // to determine controller roles per switch.
+ private RoleChanger roleChanger;
+ // Used to coordinate between the controller and the cleanup thread(?)
+ // for access to the global registry on a per switch basis.
+ volatile Boolean controlRequested;
+ // When a switch with a duplicate dpid is found (i.e we already have a
+ // connected switch with the same dpid), the new switch is immediately
+ // disconnected. At that point netty callsback channelDisconnected() which
+ // proceeds to cleaup switch state - we need to ensure that it does not cleanup
+ // switch state for the older (still connected) switch
+ private volatile Boolean duplicateDpidFound;
+
+ // Temporary storage for switch-features and port-description
+ private OFFeaturesReply featuresReply;
+ private OFPortDescStatsReply portDescReply;
+ // a concurrent ArrayList to temporarily store port status messages
+ // before we are ready to deal with them
+ private final CopyOnWriteArrayList<OFPortStatus> pendingPortStatusMsg;
+
+ //Indicates the openflow version used by this switch
+ protected OFVersion ofVersion;
+ protected OFFactory factory13;
+ protected OFFactory factory10;
+
+ /** transaction Ids to use during handshake. Since only one thread
+ * calls into an OFChannelHandler instance, we don't need atomic.
+ * We will count down
+ */
+ private int handshakeTransactionIds = -1;
+
+ /**
+ * Create a new unconnected OFChannelHandler.
+ * @param controller
+ */
+ OFChannelHandler(Controller controller) {
+ this.controller = controller;
+ this.counters = controller.getCounters();
+ this.roleChanger = new RoleChanger(DEFAULT_ROLE_TIMEOUT_MS);
+ this.state = ChannelState.INIT;
+ this.pendingPortStatusMsg = new CopyOnWriteArrayList<OFPortStatus>();
+ factory13 = controller.getOFMessageFactory13();
+ factory10 = controller.getOFMessageFactory10();
+ controlRequested = Boolean.FALSE;
+ duplicateDpidFound = Boolean.FALSE;
+ }
+
+ //*******************
+ // Role Handling
+ //*******************
+
+ /**
+ * When we remove a pending role request we use this enum to indicate how we
+ * arrived at the decision. When we send a role request to the switch, we
+ * also use this enum to indicate what we expect back from the switch, so the
+ * role changer can match the reply to our expectation.
+ */
+ public enum RoleRecvStatus {
+ /** The switch returned an error indicating that roles are not.
+ * supported*/
+ UNSUPPORTED,
+ /** The request timed out. */
+ NO_REPLY,
+ /** The reply was old, there is a newer request pending. */
+ OLD_REPLY,
+ /**
+ * The reply's role matched the role that this controller set in the
+ * request message - invoked either initially at startup or to reassert
+ * current role.
+ */
+ MATCHED_CURRENT_ROLE,
+ /**
+ * The reply's role matched the role that this controller set in the
+ * request message - this is the result of a callback from the
+ * global registry, followed by a role request sent to the switch.
+ */
+ MATCHED_SET_ROLE,
+ /**
+ * The reply's role was a response to the query made by this controller.
+ */
+ REPLY_QUERY,
+ /** We received a role reply message from the switch
+ * but the expectation was unclear, or there was no expectation.
+ */
+ OTHER_EXPECTATION,
+ }
+
+ /**
+ * Forwards to RoleChanger. See there.
+ * @param role
+ */
+ public void sendRoleRequest(Role role, RoleRecvStatus expectation) {
+ try {
+ roleChanger.sendRoleRequest(role, expectation);
+ } catch (IOException e) {
+ log.error("Disconnecting switch {} due to IO Error: {}",
+ getSwitchInfoString(), e.getMessage());
+ channel.close();
+ }
+ }
+
+ // XXX S consider if necessary
+ public void disconnectSwitch() {
+ sw.disconnectSwitch();
+ }
+
+ /**
+ * A utility class to handle role requests and replies for this channel.
+ * After a role request is submitted the role changer keeps track of the
+ * pending request, collects the reply (if any) and times out the request
+ * if necessary.
+ *
+ * To simplify role handling we only keep track of the /last/ pending
+ * role reply send to the switch. If multiple requests are pending and
+ * we receive replies for earlier requests we ignore them. However, this
+ * way of handling pending requests implies that we could wait forever if
+ * a new request is submitted before the timeout triggers. If necessary
+ * we could work around that though.
+ */
+ private class RoleChanger {
+ // indicates that a request is currently pending
+ // needs to be volatile to allow correct double-check idiom
+ private volatile boolean requestPending;
+ // the transaction Id of the pending request
+ private int pendingXid;
+ // the role that's pending
+ private Role pendingRole;
+ // system time in MS when we send the request
+ private long roleSubmitTime;
+ // the timeout to use
+ private final long roleTimeoutMs;
+ // the expectation set by the caller for the returned role
+ private RoleRecvStatus expectation;
+
+ public RoleChanger(long roleTimeoutMs) {
+ this.requestPending = false;
+ this.roleSubmitTime = 0;
+ this.pendingXid = -1;
+ this.pendingRole = null;
+ this.roleTimeoutMs = roleTimeoutMs;
+ this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE;
+ }
+
+ /**
+ * Send NX role request message to the switch requesting the specified
+ * role.
+ *
+ * @param sw switch to send the role request message to
+ * @param role role to request
+ */
+ private int sendNxRoleRequest(Role role) throws IOException {
+ // Convert the role enum to the appropriate role to send
+ OFNiciraControllerRole roleToSend = OFNiciraControllerRole.ROLE_OTHER;
+ switch (role) {
+ case MASTER:
+ roleToSend = OFNiciraControllerRole.ROLE_MASTER;
+ break;
+ case SLAVE:
+ case EQUAL:
+ default:
+ // ensuring that the only two roles sent to 1.0 switches with
+ // Nicira role support, are MASTER and SLAVE
+ roleToSend = OFNiciraControllerRole.ROLE_SLAVE;
+ log.warn("Sending Nx Role.SLAVE to switch {}.", sw);
+ }
+ int xid = sw.getNextTransactionId();
+ OFExperimenter roleRequest = factory10
+ .buildNiciraControllerRoleRequest()
+ .setXid(xid)
+ .setRole(roleToSend)
+ .build();
+ sw.write(Collections.<OFMessage>singletonList(roleRequest));
+ return xid;
+ }
+
+ private int sendOF13RoleRequest(Role role) throws IOException {
+ // Convert the role enum to the appropriate role to send
+ OFControllerRole roleToSend = OFControllerRole.ROLE_NOCHANGE;
+ switch (role) {
+ case EQUAL:
+ roleToSend = OFControllerRole.ROLE_EQUAL;
+ break;
+ case MASTER:
+ roleToSend = OFControllerRole.ROLE_MASTER;
+ break;
+ case SLAVE:
+ roleToSend = OFControllerRole.ROLE_SLAVE;
+ break;
+ default:
+ log.warn("Sending default role.noChange to switch {}."
+ + " Should only be used for queries.", sw);
+ }
+
+ int xid = sw.getNextTransactionId();
+ OFRoleRequest rrm = factory13
+ .buildRoleRequest()
+ .setRole(roleToSend)
+ .setXid(xid)
+ .setGenerationId(sw.getNextGenerationId())
+ .build();
+ sw.write(rrm);
+ return xid;
+ }
+
+ /**
+ * Send a role request with the given role to the switch and update
+ * the pending request and timestamp.
+ * Sends an OFPT_ROLE_REQUEST to an OF1.3 switch, OR
+ * Sends an NX_ROLE_REQUEST to an OF1.0 switch if configured to support it
+ * in the IOFSwitch driver. If not supported, this method sends nothing
+ * and returns 'false'. The caller should take appropriate action.
+ *
+ * One other optimization we do here is that for OF1.0 switches with
+ * Nicira role message support, we force the Role.EQUAL to become
+ * Role.SLAVE, as there is no defined behavior for the Nicira role OTHER.
+ * We cannot expect it to behave like SLAVE. We don't have this problem with
+ * OF1.3 switches, because Role.EQUAL is well defined and we can simulate
+ * SLAVE behavior by using ASYNC messages.
+ *
+ * @param role
+ * @throws IOException
+ * @returns false if and only if the switch does not support role-request
+ * messages, according to the switch driver; true otherwise.
+ */
+ synchronized boolean sendRoleRequest(Role role, RoleRecvStatus exp)
+ throws IOException {
+ this.expectation = exp;
+
+ if (ofVersion == OFVersion.OF_10) {
+ Boolean supportsNxRole = (Boolean)
+ sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE);
+ if (!supportsNxRole) {
+ log.debug("Switch driver indicates no support for Nicira "
+ + "role request messages. Not sending ...");
+ state.handleUnsentRoleMessage(OFChannelHandler.this, role,
+ expectation);
+ return false;
+ }
+ // OF1.0 switch with support for NX_ROLE_REQUEST vendor extn.
+ // make Role.EQUAL become Role.SLAVE
+ role = (role == Role.EQUAL) ? Role.SLAVE : role;
+ pendingXid = sendNxRoleRequest(role);
+ pendingRole = role;
+ roleSubmitTime = System.currentTimeMillis();
+ requestPending = true;
+ } else {
+ // OF1.3 switch, use OFPT_ROLE_REQUEST message
+ pendingXid = sendOF13RoleRequest(role);
+ pendingRole = role;
+ roleSubmitTime = System.currentTimeMillis();
+ requestPending = true;
+ }
+ return true;
+ }
+
+ /**
+ * Deliver a received role reply.
+ *
+ * Check if a request is pending and if the received reply matches the
+ * the expected pending reply (we check both role and xid) we set
+ * the role for the switch/channel.
+ *
+ * If a request is pending but doesn't match the reply we ignore it, and
+ * return
+ *
+ * If no request is pending we disconnect with a SwitchStateException
+ *
+ * @param RoleReplyInfo information about role-reply in format that
+ * controller can understand.
+ * @throws SwitchStateException if no request is pending
+ */
+ synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
+ throws SwitchStateException {
+ if (!requestPending) {
+ Role currentRole = (sw != null) ? sw.getRole() : null;
+ if (currentRole != null) {
+ if (currentRole == rri.getRole()) {
+ // Don't disconnect if the role reply we received is
+ // for the same role we are already in.
+ log.debug("Received unexpected RoleReply from "
+ + "Switch: {} in State: {}. "
+ + "Role in reply is same as current role of this "
+ + "controller for this sw. Ignoring ...",
+ getSwitchInfoString(), state.toString());
+ return RoleRecvStatus.OTHER_EXPECTATION;
+ } else {
+ String msg = String.format("Switch: [%s], State: [%s], "
+ + "received unexpected RoleReply[%s]. "
+ + "No roles are pending, and this controller's "
+ + "current role:[%s] does not match reply. "
+ + "Disconnecting switch ... ",
+ OFChannelHandler.this.getSwitchInfoString(),
+ OFChannelHandler.this.state.toString(),
+ rri, currentRole);
+ throw new SwitchStateException(msg);
+ }
+ }
+ log.debug("Received unexpected RoleReply {} from "
+ + "Switch: {} in State: {}. "
+ + "This controller has no current role for this sw. "
+ + "Ignoring ...", new Object[] {rri,
+ getSwitchInfoString(), state});
+ return RoleRecvStatus.OTHER_EXPECTATION;
+ }
+
+ int xid = (int) rri.getXid();
+ Role role = rri.getRole();
+ // XXX S should check generation id meaningfully and other cases of expectations
+ // U64 genId = rri.getGenId();
+
+ if (pendingXid != xid) {
+ log.debug("Received older role reply from " +
+ "switch {} ({}). Ignoring. " +
+ "Waiting for {}, xid={}",
+ new Object[] {getSwitchInfoString(), rri,
+ pendingRole, pendingXid });
+ return RoleRecvStatus.OLD_REPLY;
+ }
+
+ if (pendingRole == role) {
+ log.debug("Received role reply message from {} that matched "
+ + "expected role-reply {} with expectations {}",
+ new Object[] {getSwitchInfoString(), role, expectation});
+ counters.roleReplyReceived.updateCounterWithFlush();
+ //setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY); dont want to set state here
+ if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE ||
+ expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
+ return expectation;
+ } else {
+ return RoleRecvStatus.OTHER_EXPECTATION;
+ }
+ }
+
+ // if xids match but role's don't, perhaps its a query (OF1.3)
+ if (expectation == RoleRecvStatus.REPLY_QUERY) {
+ return expectation;
+ }
+
+ return RoleRecvStatus.OTHER_EXPECTATION;
+ }
+
+ /**
+ * Called if we receive an error message. If the xid matches the
+ * pending request we handle it otherwise we ignore it.
+ *
+ * Note: since we only keep the last pending request we might get
+ * error messages for earlier role requests that we won't be able
+ * to handle
+ */
+ synchronized RoleRecvStatus deliverError(OFErrorMsg error)
+ throws SwitchStateException {
+ if (!requestPending) {
+ log.debug("Received an error msg from sw {}, but no pending "
+ + "requests in role-changer; not handling ...",
+ getSwitchInfoString());
+ return RoleRecvStatus.OTHER_EXPECTATION;
+ }
+ if (pendingXid != error.getXid()) {
+ if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
+ log.debug("Received an error msg from sw {} for a role request,"
+ + " but not for pending request in role-changer; "
+ + " ignoring error {} ...",
+ getSwitchInfoString(), error);
+ }
+ return RoleRecvStatus.OTHER_EXPECTATION;
+ }
+ // it is an error related to a currently pending role request message
+ if (error.getErrType() == OFErrorType.BAD_REQUEST) {
+ counters.roleReplyErrorUnsupported.updateCounterWithFlush();
+ log.error("Received a error msg {} from sw {} in state {} for "
+ + "pending role request {}. Switch driver indicates "
+ + "role-messaging is supported. Possible issues in "
+ + "switch driver configuration?", new Object[] {
+ ((OFBadRequestErrorMsg) error).toString(),
+ getSwitchInfoString(), state, pendingRole
+ });
+ return RoleRecvStatus.UNSUPPORTED;
+ }
+
+ if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
+ OFRoleRequestFailedErrorMsg rrerr =
+ (OFRoleRequestFailedErrorMsg) error;
+ switch (rrerr.getCode()) {
+ case BAD_ROLE:
+ // switch says that current-role-req has bad role?
+ // for now we disconnect
+ // fall-thru
+ case STALE:
+ // switch says that current-role-req has stale gen-id?
+ // for now we disconnect
+ // fall-thru
+ case UNSUP:
+ // switch says that current-role-req has role that
+ // cannot be supported? for now we disconnect
+ String msgx = String.format("Switch: [%s], State: [%s], "
+ + "received Error to for pending role request [%s]. "
+ + "Error:[%s]. Disconnecting switch ... ",
+ OFChannelHandler.this.getSwitchInfoString(),
+ OFChannelHandler.this.state.toString(),
+ pendingRole, rrerr);
+ throw new SwitchStateException(msgx);
+ default:
+ break;
+ }
+ }
+
+ // This error message was for a role request message but we dont know
+ // how to handle errors for nicira role request messages
+ return RoleRecvStatus.OTHER_EXPECTATION;
+ }
+
+ /**
+ * Check if a pending role request has timed out.
+ */
+ void checkTimeout() {
+ if (!requestPending) {
+ return;
+ }
+ synchronized (this) {
+ if (!requestPending) {
+ return;
+ }
+ long now = System.currentTimeMillis();
+ if (now - roleSubmitTime > roleTimeoutMs) {
+ // timeout triggered.
+ counters.roleReplyTimeout.updateCounterWithFlush();
+ //setSwitchRole(pendingRole, RoleRecvStatus.NO_REPLY);
+ // XXX S come back to this
+ }
+ }
+ }
+
+ }
+
+ //*************************
+ // Channel State Machine
+ //*************************
+
+ /**
+ * The state machine for handling the switch/channel state. All state
+ * transitions should happen from within the state machine (and not from other
+ * parts of the code)
+ */
+ enum ChannelState {
+ /**
+ * Initial state before channel is connected.
+ */
+ INIT(false) {
+ @Override
+ void processOFMessage(OFChannelHandler h, OFMessage m)
+ throws IOException, SwitchStateException {
+ illegalMessageReceived(h, m);
+ }
+
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m)
+ throws IOException {
+ // need to implement since its abstract but it will never
+ // be called
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException {
+ unhandledMessageReceived(h, m);
+ }
+ },
+
+ /**
+ * We send a OF 1.3 HELLO to the switch and wait for a Hello from the switch.
+ * Once we receive the reply, we decide on OF 1.3 or 1.0 switch - no other
+ * protocol version is accepted.
+ * We send an OFFeaturesRequest depending on the protocol version selected
+ * Next state is WAIT_FEATURES_REPLY
+ */
+ WAIT_HELLO(false) {
+ @Override
+ void processOFHello(OFChannelHandler h, OFHello m)
+ throws IOException {
+ // TODO We could check for the optional bitmap, but for now
+ // we are just checking the version number.
+ if (m.getVersion() == OFVersion.OF_13) {
+ log.info("Received {} Hello from {}", m.getVersion(),
+ h.channel.getRemoteAddress());
+ h.ofVersion = OFVersion.OF_13;
+ } else if (m.getVersion() == OFVersion.OF_10) {
+ log.info("Received {} Hello from {} - switching to OF "
+ + "version 1.0", m.getVersion(),
+ h.channel.getRemoteAddress());
+ h.ofVersion = OFVersion.OF_10;
+ } else {
+ log.error("Received Hello of version {} from switch at {}. "
+ + "This controller works with OF1.0 and OF1.3 "
+ + "switches. Disconnecting switch ...",
+ m.getVersion(), h.channel.getRemoteAddress());
+ h.channel.disconnect();
+ return;
+ }
+ h.sendHandshakeFeaturesRequestMessage();
+ h.setState(WAIT_FEATURES_REPLY);
+ }
+ @Override
+ void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
+ throws IOException, SwitchStateException {
+ illegalMessageReceived(h, m);
+ }
+ @Override
+ void processOFStatisticsReply(OFChannelHandler h,
+ OFStatsReply m)
+ throws IOException, SwitchStateException {
+ illegalMessageReceived(h, m);
+ }
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m) {
+ logErrorDisconnect(h, m);
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException {
+ unhandledMessageReceived(h, m);
+ }
+ },
+
+
+ /**
+ * We are waiting for a features reply message. Once we receive it, the
+ * behavior depends on whether this is a 1.0 or 1.3 switch. For 1.0,
+ * we send a SetConfig request, barrier, and GetConfig request and the
+ * next state is WAIT_CONFIG_REPLY. For 1.3, we send a Port description
+ * request and the next state is WAIT_PORT_DESC_REPLY.
+ */
+ WAIT_FEATURES_REPLY(false) {
+ @Override
+ void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
+ throws IOException {
+ h.thisdpid = m.getDatapathId().getLong();
+ log.info("Received features reply for switch at {} with dpid {}",
+ h.getSwitchInfoString(), h.thisdpid);
+ //update the controller about this connected switch
+ boolean success = h.controller.addConnectedSwitch(
+ h.thisdpid, h);
+ if (!success) {
+ disconnectDuplicate(h);
+ return;
+ }
+
+ h.featuresReply = m; //temp store
+ if (h.ofVersion == OFVersion.OF_10) {
+ h.sendHandshakeSetConfig();
+ h.setState(WAIT_CONFIG_REPLY);
+ } else {
+ //version is 1.3, must get switchport information
+ h.sendHandshakeOFPortDescRequest();
+ h.setState(WAIT_PORT_DESC_REPLY);
+ }
+ }
+ @Override
+ void processOFStatisticsReply(OFChannelHandler h,
+ OFStatsReply m)
+ throws IOException, SwitchStateException {
+ illegalMessageReceived(h, m);
+ }
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m) {
+ logErrorDisconnect(h, m);
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException {
+ unhandledMessageReceived(h, m);
+ }
+ },
+
+ /**
+ * We are waiting for a description of the 1.3 switch ports.
+ * Once received, we send a SetConfig request
+ * Next State is WAIT_CONFIG_REPLY
+ */
+ WAIT_PORT_DESC_REPLY(false) {
+
+ @Override
+ void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
+ throws SwitchStateException {
+ // Read port description
+ if (m.getStatsType() != OFStatsType.PORT_DESC) {
+ log.warn("Expecting port description stats but received stats "
+ + "type {} from {}. Ignoring ...", m.getStatsType(),
+ h.channel.getRemoteAddress());
+ return;
+ }
+ if (m.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
+ log.warn("Stats reply indicates more stats from sw {} for "
+ + "port description - not currently handled",
+ h.getSwitchInfoString());
+ }
+ h.portDescReply = (OFPortDescStatsReply) m; // temp store
+ log.info("Received port desc reply for switch at {}",
+ h.getSwitchInfoString());
+ try {
+ h.sendHandshakeSetConfig();
+ } catch (IOException e) {
+ log.error("Unable to send setConfig after PortDescReply. "
+ + "Error: {}", e.getMessage());
+ }
+ h.setState(WAIT_CONFIG_REPLY);
+ }
+
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m)
+ throws IOException, SwitchStateException {
+ logErrorDisconnect(h, m);
+
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException, SwitchStateException {
+ unhandledMessageReceived(h, m);
+
+ }
+ },
+
+ /**
+ * We are waiting for a config reply message. Once we receive it
+ * we send a DescriptionStatsRequest to the switch.
+ * Next state: WAIT_DESCRIPTION_STAT_REPLY
+ */
+ WAIT_CONFIG_REPLY(false) {
+ @Override
+ @LogMessageDocs({
+ @LogMessageDoc(level = "WARN",
+ message = "Config Reply from {switch} has "
+ + "miss length set to {length}",
+ explanation = "The controller requires that the switch "
+ + "use a miss length of 0xffff for correct "
+ + "function",
+ recommendation = "Use a different switch to ensure "
+ + "correct function")
+ })
+ void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m)
+ throws IOException {
+ if (m.getMissSendLen() == 0xffff) {
+ log.trace("Config Reply from switch {} confirms "
+ + "miss length set to 0xffff",
+ h.getSwitchInfoString());
+ } else {
+ // FIXME: we can't really deal with switches that don't send
+ // full packets. Shouldn't we drop the connection here?
+ log.warn("Config Reply from switch {} has"
+ + "miss length set to {}",
+ h.getSwitchInfoString(),
+ m.getMissSendLen());
+ }
+ h.sendHandshakeDescriptionStatsRequest();
+ h.setState(WAIT_DESCRIPTION_STAT_REPLY);
+ }
+
+ @Override
+ void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m) {
+ // do nothing;
+ }
+
+ @Override
+ void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
+ throws IOException, SwitchStateException {
+ illegalMessageReceived(h, m);
+ }
+ @Override
+ void processOFStatisticsReply(OFChannelHandler h,
+ OFStatsReply m)
+ throws IOException, SwitchStateException {
+ log.error("Received multipart(stats) message sub-type {}",
+ m.getStatsType());
+ illegalMessageReceived(h, m);
+ }
+
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m) {
+ logErrorDisconnect(h, m);
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException {
+ h.pendingPortStatusMsg.add(m);
+ }
+ },
+
+
+ /**
+ * We are waiting for a OFDescriptionStat message from the switch.
+ * Once we receive any stat message we try to parse it. If it's not
+ * a description stats message we disconnect. If its the expected
+ * description stats message, we:
+ * - use the switch driver to bind the switch and get an IOFSwitch instance
+ * - setup the IOFSwitch instance
+ * - add switch controller and send the initial role
+ * request to the switch.
+ * Next state: WAIT_INITIAL_ROLE
+ * In the typical case, where switches support role request messages
+ * the next state is where we expect the role reply message.
+ * In the special case that where the switch does not support any kind
+ * of role request messages, we don't send a role message, but we do
+ * request mastership from the registry service. This controller
+ * should become master once we hear back from the registry service.
+ * All following states will have a h.sw instance!
+ */
+ WAIT_DESCRIPTION_STAT_REPLY(false) {
+ @LogMessageDoc(message = "Switch {switch info} bound to class "
+ + "{switch driver}, description {switch description}",
+ explanation = "The specified switch has been bound to "
+ + "a switch driver based on the switch description"
+ + "received from the switch")
+ @Override
+ void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
+ throws SwitchStateException {
+ // Read description, if it has been updated
+ if (m.getStatsType() != OFStatsType.DESC) {
+ log.warn("Expecting Description stats but received stats "
+ + "type {} from {}. Ignoring ...", m.getStatsType(),
+ h.channel.getRemoteAddress());
+ return;
+ }
+ log.info("Received switch description reply from switch at {}",
+ h.channel.getRemoteAddress());
+ OFDescStatsReply drep = (OFDescStatsReply) m;
+ // Here is where we differentiate between different kinds of switches
+ h.sw = h.controller.getOFSwitchInstance(drep, h.ofVersion);
+ // set switch information
+ h.sw.setOFVersion(h.ofVersion);
+ h.sw.setFeaturesReply(h.featuresReply);
+ h.sw.setPortDescReply(h.portDescReply);
+ h.sw.setConnected(true);
+ h.sw.setChannel(h.channel);
+
+ try {
+ h.sw.setDebugCounterService(h.controller.getDebugCounter());
+ } catch (CounterException e) {
+ h.counters.switchCounterRegistrationFailed
+ .updateCounterNoFlush();
+ log.warn("Could not register counters for switch {} ",
+ h.getSwitchInfoString(), e);
+ }
+
+ log.info("Switch {} bound to class {}, description {}",
+ new Object[] {h.sw, h.sw.getClass(), drep });
+ //Put switch in EQUAL mode until we hear back from the global registry
+ log.debug("Setting new switch {} to EQUAL and sending Role request",
+ h.sw.getStringId());
+ h.setSwitchRole(Role.EQUAL);
+ try {
+ boolean supportsRRMsg = h.roleChanger.sendRoleRequest(Role.EQUAL,
+ RoleRecvStatus.MATCHED_CURRENT_ROLE);
+ if (!supportsRRMsg) {
+ log.warn("Switch {} does not support role request messages "
+ + "of any kind. No role messages were sent. "
+ + "This controller instance SHOULD become MASTER "
+ + "from the registry process. ",
+ h.getSwitchInfoString());
+ }
+ h.setState(WAIT_INITIAL_ROLE);
+ // request control of switch from global registry -
+ // necessary even if this is the only controller the
+ // switch is connected to.
+ h.controller.submitRegistryRequest(h.sw.getId());
+ } catch (IOException e) {
+ log.error("Exception when sending role request: {} ",
+ e.getMessage());
+ // FIXME shouldn't we disconnect?
+ }
+ }
+
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m) {
+ logErrorDisconnect(h, m);
+ }
+
+ @Override
+ void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
+ throws IOException, SwitchStateException {
+ illegalMessageReceived(h, m);
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException {
+ h.pendingPortStatusMsg.add(m);
+ }
+ },
+
+ /**
+ * We are waiting for a role reply message in response to a role request
+ * sent after hearing back from the registry service -- OR -- we are
+ * just waiting to hear back from the registry service in the case that
+ * the switch does not support role messages. If completed successfully,
+ * the controller's role for this switch will be set here.
+ * Before we move to the state corresponding to the role, we allow the
+ * switch specific driver to complete its configuration. This configuration
+ * typically depends on the role the controller is playing for this switch.
+ * And so we set the switch role (for 'this' controller) before we start
+ * the driver-sub-handshake.
+ * Next State: WAIT_SWITCH_DRIVER_SUB_HANDSHAKE
+ */
+ WAIT_INITIAL_ROLE(false) {
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m)
+ throws SwitchStateException {
+ // role changer will ignore the error if it isn't for it
+ RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
+ if (rrstatus == RoleRecvStatus.OTHER_EXPECTATION) {
+ logError(h, m);
+ }
+ }
+
+ @Override
+ void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
+ throws IOException, SwitchStateException {
+ Role role = extractNiciraRoleReply(h, m);
+ // If role == null it means the vendor (experimenter) message
+ // wasn't really a Nicira role reply. We ignore this case.
+ if (role != null) {
+ RoleReplyInfo rri = new RoleReplyInfo(role, null, m.getXid());
+ RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
+ if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+ setRoleAndStartDriverHandshake(h, rri.getRole());
+ } // else do nothing - wait for the correct expected reply
+ } else {
+ unhandledMessageReceived(h, m);
+ }
+ }
+
+ @Override
+ void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
+ throws SwitchStateException, IOException {
+ RoleReplyInfo rri = extractOFRoleReply(h, m);
+ RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
+ if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+ setRoleAndStartDriverHandshake(h, rri.getRole());
+ } // else do nothing - wait for the correct expected reply
+ }
+
+ @Override
+ void handleUnsentRoleMessage(OFChannelHandler h, Role role,
+ RoleRecvStatus expectation) throws IOException {
+ // typically this is triggered for a switch where role messages
+ // are not supported - we confirm that the role being set is
+ // master and move to the next state
+ if (expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
+ if (role == Role.MASTER) {
+ setRoleAndStartDriverHandshake(h, role);
+ } else {
+ log.error("Expected MASTER role from registry for switch "
+ + "which has no support for role-messages."
+ + "Received {}. It is possible that this switch "
+ + "is connected to other controllers, in which "
+ + "case it should support role messages - not "
+ + "moving forward.", role);
+ }
+ } // else do nothing - wait to hear back from registry
+
+ }
+
+ private void setRoleAndStartDriverHandshake(OFChannelHandler h,
+ Role role) throws IOException {
+ h.setSwitchRole(role);
+ h.sw.startDriverHandshake();
+ if (h.sw.isDriverHandshakeComplete()) {
+ Role mySwitchRole = h.sw.getRole();
+ if (mySwitchRole == Role.MASTER) {
+ log.info("Switch-driver sub-handshake complete. "
+ + "Activating switch {} with Role: MASTER",
+ h.getSwitchInfoString());
+ handlePendingPortStatusMessages(h); //before activation
+ boolean success = h.controller.addActivatedMasterSwitch(
+ h.sw.getId(), h.sw);
+ if (!success) {
+ disconnectDuplicate(h);
+ return;
+ }
+ h.setState(MASTER);
+ } else {
+ log.info("Switch-driver sub-handshake complete. "
+ + "Activating switch {} with Role: EQUAL",
+ h.getSwitchInfoString());
+ handlePendingPortStatusMessages(h); //before activation
+ boolean success = h.controller.addActivatedEqualSwitch(
+ h.sw.getId(), h.sw);
+ if (!success) {
+ disconnectDuplicate(h);
+ return;
+ }
+ h.setState(EQUAL);
+ }
+ } else {
+ h.setState(WAIT_SWITCH_DRIVER_SUB_HANDSHAKE);
+ }
+ }
+
+ @Override
+ void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
+ throws IOException, SwitchStateException {
+ illegalMessageReceived(h, m);
+ }
+
+ @Override
+ void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
+ throws SwitchStateException {
+ illegalMessageReceived(h, m);
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException, SwitchStateException {
+ h.pendingPortStatusMsg.add(m);
+
+ }
+ },
+
+ /**
+ * We are waiting for the respective switch driver to complete its
+ * configuration. Notice that we do not consider this to be part of the main
+ * switch-controller handshake. But we do consider it as a step that comes
+ * before we declare the switch as available to the controller.
+ * Next State: depends on the role of this controller for this switch - either
+ * MASTER or EQUAL.
+ */
+ WAIT_SWITCH_DRIVER_SUB_HANDSHAKE(true) {
+
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m)
+ throws IOException {
+ // will never be called. We override processOFMessage
+ }
+
+ @Override
+ void processOFMessage(OFChannelHandler h, OFMessage m)
+ throws IOException {
+ if (m.getType() == OFType.ECHO_REQUEST) {
+ processOFEchoRequest(h, (OFEchoRequest) m);
+ } else {
+ // FIXME: other message to handle here?
+ h.sw.processDriverHandshakeMessage(m);
+ if (h.sw.isDriverHandshakeComplete()) {
+ // consult the h.sw role and goto that state
+ Role mySwitchRole = h.sw.getRole();
+ if (mySwitchRole == Role.MASTER) {
+ log.info("Switch-driver sub-handshake complete. "
+ + "Activating switch {} with Role: MASTER",
+ h.getSwitchInfoString());
+ handlePendingPortStatusMessages(h); //before activation
+ boolean success = h.controller.addActivatedMasterSwitch(
+ h.sw.getId(), h.sw);
+ if (!success) {
+ disconnectDuplicate(h);
+ return;
+ }
+ h.setState(MASTER);
+ } else {
+ log.info("Switch-driver sub-handshake complete. "
+ + "Activating switch {} with Role: EQUAL",
+ h.getSwitchInfoString());
+ handlePendingPortStatusMessages(h); //before activation
+ boolean success = h.controller.addActivatedEqualSwitch(
+ h.sw.getId(), h.sw);
+ if (!success) {
+ disconnectDuplicate(h);
+ return;
+ }
+ h.setState(EQUAL);
+ }
+ }
+ }
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException, SwitchStateException {
+ h.pendingPortStatusMsg.add(m);
+ }
+ },
+
+
+ /**
+ * This controller is in MASTER role for this switch. We enter this state
+ * after requesting and winning control from the global registry.
+ * The main handshake as well as the switch-driver sub-handshake
+ * is complete at this point.
+ * // XXX S reconsider below
+ * In the (near) future we may deterministically assign controllers to
+ * switches at startup.
+ * We only leave this state if the switch disconnects or
+ * if we send a role request for SLAVE /and/ receive the role reply for
+ * SLAVE.
+ */
+ MASTER(true) {
+ @LogMessageDoc(level = "WARN",
+ message = "Received permission error from switch {} while"
+ + "being master. Reasserting master role.",
+ explanation = "The switch has denied an operation likely "
+ + "indicating inconsistent controller roles",
+ recommendation = "This situation can occurs transiently during role"
+ + " changes. If, however, the condition persists or happens"
+ + " frequently this indicates a role inconsistency. "
+ + LogMessageDoc.CHECK_CONTROLLER)
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m)
+ throws IOException, SwitchStateException {
+ // first check if the error msg is in response to a role-request message
+ RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
+ if (rrstatus != RoleRecvStatus.OTHER_EXPECTATION) {
+ // rolechanger has handled the error message - we are done
+ return;
+ }
+
+ // if we get here, then the error message is for something else
+ if (m.getErrType() == OFErrorType.BAD_REQUEST &&
+ ((OFBadRequestErrorMsg) m).getCode() ==
+ OFBadRequestCode.EPERM) {
+ // We are the master controller and the switch returned
+ // a permission error. This is a likely indicator that
+ // the switch thinks we are slave. Reassert our
+ // role
+ // FIXME: this could be really bad during role transitions
+ // if two controllers are master (even if its only for
+ // a brief period). We might need to see if these errors
+ // persist before we reassert
+ h.counters.epermErrorWhileSwitchIsMaster.updateCounterWithFlush();
+ log.warn("Received permission error from switch {} while" +
+ "being master. Reasserting master role.",
+ h.getSwitchInfoString());
+ //h.controller.reassertRole(h, Role.MASTER);
+ // XXX S reassert in role changer or reconsider if all this
+ // stuff is really needed
+ } else if (m.getErrType() == OFErrorType.FLOW_MOD_FAILED &&
+ ((OFFlowModFailedErrorMsg) m).getCode() ==
+ OFFlowModFailedCode.ALL_TABLES_FULL) {
+ h.sw.setTableFull(true);
+ } else {
+ logError(h, m);
+ }
+ h.dispatchMessage(m);
+ }
+
+ @Override
+ void processOFStatisticsReply(OFChannelHandler h,
+ OFStatsReply m) {
+ h.sw.deliverStatisticsReply(m);
+ }
+
+ @Override
+ void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
+ throws IOException, SwitchStateException {
+ Role role = extractNiciraRoleReply(h, m);
+ if (role == null) {
+ // The message wasn't really a Nicira role reply. We just
+ // dispatch it to the OFMessage listeners in this case.
+ h.dispatchMessage(m);
+ return;
+ }
+
+ RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(
+ new RoleReplyInfo(role, null, m.getXid()));
+ if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+ checkAndSetRoleTransition(h, role);
+ }
+ }
+
+ @Override
+ void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
+ throws SwitchStateException, IOException {
+ RoleReplyInfo rri = extractOFRoleReply(h, m);
+ RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
+ if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+ checkAndSetRoleTransition(h, rri.getRole());
+ }
+ }
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException, SwitchStateException {
+ handlePortStatusMessage(h, m, true);
+ h.dispatchMessage(m);
+ }
+
+ @Override
+ void processOFPacketIn(OFChannelHandler h, OFPacketIn m)
+ throws IOException {
+ h.dispatchMessage(m);
+ }
+
+ @Override
+ void processOFFlowRemoved(OFChannelHandler h,
+ OFFlowRemoved m) throws IOException {
+ h.dispatchMessage(m);
+ }
+
+ @Override
+ void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m)
+ throws IOException {
+ h.dispatchMessage(m);
+ }
+
+ },
+
+ /**
+ * This controller is in EQUAL role for this switch. We enter this state
+ * after some /other/ controller instance wins mastership-role over this
+ * switch. The EQUAL role can be considered the same as the SLAVE role
+ * if this controller does NOT send commands or packets to the switch.
+ * This should always be true for OF1.0 switches. XXX S need to enforce.
+ *
+ * For OF1.3 switches, choosing this state as EQUAL instead of SLAVE,
+ * gives us the flexibility that if an app wants to send commands/packets
+ * to switches, it can, even thought it is running on a controller instance
+ * that is not in a MASTER role for this switch. Of course, it is the job
+ * of the app to ensure that commands/packets sent by this (EQUAL) controller
+ * instance does not clash/conflict with commands/packets sent by the MASTER
+ * controller for this switch. Neither the controller instances, nor the
+ * switch provides any kind of resolution mechanism should conflicts occur.
+ */
+ EQUAL(true) {
+ @Override
+ void processOFError(OFChannelHandler h, OFErrorMsg m)
+ throws IOException, SwitchStateException {
+ // role changer will ignore the error if it isn't for it
+ RoleRecvStatus rrstatus = h.roleChanger.deliverError(m);
+ if (rrstatus == RoleRecvStatus.OTHER_EXPECTATION) {
+ logError(h, m);
+ h.dispatchMessage(m);
+ }
+ }
+
+ @Override
+ void processOFStatisticsReply(OFChannelHandler h,
+ OFStatsReply m) {
+ h.sw.deliverStatisticsReply(m);
+ }
+
+ @Override
+ void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
+ throws IOException, SwitchStateException {
+ Role role = extractNiciraRoleReply(h, m);
+ // If role == null it means the message wasn't really a
+ // Nicira role reply. We ignore it in this state.
+ if (role != null) {
+ RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(
+ new RoleReplyInfo(role, null, m.getXid()));
+ if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+ checkAndSetRoleTransition(h, role);
+ }
+ } else {
+ unhandledMessageReceived(h, m);
+ }
+ }
+
+ @Override
+ void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
+ throws SwitchStateException, IOException {
+ RoleReplyInfo rri = extractOFRoleReply(h, m);
+ RoleRecvStatus rrs = h.roleChanger.deliverRoleReply(rri);
+ if (rrs == RoleRecvStatus.MATCHED_SET_ROLE) {
+ checkAndSetRoleTransition(h, rri.getRole());
+ }
+ }
+
+ // XXX S needs more handlers for 1.3 switches in equal role
+
+ @Override
+ void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException, SwitchStateException {
+ handlePortStatusMessage(h, m, true);
+ }
+
+ @Override
+ @LogMessageDoc(level = "WARN",
+ message = "Received PacketIn from switch {} while "
+ + "being slave. Reasserting slave role.",
+ explanation = "The switch has receive a PacketIn despite being "
+ + "in slave role indicating inconsistent controller roles",
+ recommendation = "This situation can occurs transiently during role"
+ + " changes. If, however, the condition persists or happens"
+ + " frequently this indicates a role inconsistency. "
+ + LogMessageDoc.CHECK_CONTROLLER)
+ void processOFPacketIn(OFChannelHandler h, OFPacketIn m) throws IOException {
+ // we don't expect packetIn while slave, reassert we are slave
+ h.counters.packetInWhileSwitchIsSlave.updateCounterNoFlush();
+ log.warn("Received PacketIn from switch {} while" +
+ "being slave. Reasserting slave role.", h.sw);
+ //h.controller.reassertRole(h, Role.SLAVE);
+ // XXX reassert in role changer
+ }
+ };
+
+ private final boolean handshakeComplete;
+ ChannelState(boolean handshakeComplete) {
+ this.handshakeComplete = handshakeComplete;
+ }
+
+ /**
+ * Is this a state in which the handshake has completed?
+ * @return true if the handshake is complete
+ */
+ public boolean isHandshakeComplete() {
+ return handshakeComplete;
+ }
+
+ /**
+ * Get a string specifying the switch connection, state, and
+ * message received. To be used as message for SwitchStateException
+ * or log messages
+ * @param h The channel handler (to get switch information_
+ * @param m The OFMessage that has just been received
+ * @param details A string giving more details about the exact nature
+ * of the problem.
+ * @return
+ */
+ // needs to be protected because enum members are actually subclasses
+ protected String getSwitchStateMessage(OFChannelHandler h,
+ OFMessage m,
+ String details) {
+ return String.format("Switch: [%s], State: [%s], received: [%s]"
+ + ", details: %s",
+ h.getSwitchInfoString(),
+ this.toString(),
+ m.getType().toString(),
+ details);
+ }
+
+ /**
+ * We have an OFMessage we didn't expect given the current state and
+ * we want to treat this as an error.
+ * We currently throw an exception that will terminate the connection
+ * However, we could be more forgiving
+ * @param h the channel handler that received the message
+ * @param m the message
+ * @throws SwitchStateException
+ * @throws SwitchStateExeption we always through the execption
+ */
+ // needs to be protected because enum members are acutally subclasses
+ protected void illegalMessageReceived(OFChannelHandler h, OFMessage m)
+ throws SwitchStateException {
+ String msg = getSwitchStateMessage(h, m,
+ "Switch should never send this message in the current state");
+ throw new SwitchStateException(msg);
+
+ }
+
+ /**
+ * We have an OFMessage we didn't expect given the current state and
+ * we want to ignore the message.
+ * @param h the channel handler the received the message
+ * @param m the message
+ */
+ protected void unhandledMessageReceived(OFChannelHandler h,
+ OFMessage m) {
+ h.counters.unhandledMessage.updateCounterNoFlush();
+ if (log.isDebugEnabled()) {
+ String msg = getSwitchStateMessage(h, m,
+ "Ignoring unexpected message");
+ log.debug(msg);
+ }
+ }
+
+ /**
+ * Log an OpenFlow error message from a switch.
+ * @param sw The switch that sent the error
+ * @param error The error message
+ */
+ @LogMessageDoc(level = "ERROR",
+ message = "Error {error type} {error code} from {switch} "
+ + "in state {state}",
+ explanation = "The switch responded with an unexpected error"
+ + "to an OpenFlow message from the controller",
+ recommendation = "This could indicate improper network operation. "
+ + "If the problem persists restarting the switch and "
+ + "controller may help."
+ )
+ protected void logError(OFChannelHandler h, OFErrorMsg error) {
+ log.error("{} from switch {} in state {}",
+ new Object[] {
+ error,
+ h.getSwitchInfoString(),
+ this.toString()});
+ }
+
+ /**
+ * Log an OpenFlow error message from a switch and disconnect the
+ * channel.
+ *
+ * @param h the IO channel for this switch.
+ * @param error The error message
+ */
+ protected void logErrorDisconnect(OFChannelHandler h, OFErrorMsg error) {
+ logError(h, error);
+ h.channel.disconnect();
+ }
+
+ /**
+ * log an error message for a duplicate dpid and disconnect this channel.
+ * @param h the IO channel for this switch.
+ */
+ protected void disconnectDuplicate(OFChannelHandler h) {
+ log.error("Duplicated dpid or incompleted cleanup - "
+ + "disconnecting channel {}", h.getSwitchInfoString());
+ h.duplicateDpidFound = Boolean.TRUE;
+ h.channel.disconnect();
+ }
+
+ /**
+ * Extract the role from an OFVendor message.
+ *
+ * Extract the role from an OFVendor message if the message is a
+ * Nicira role reply. Otherwise return null.
+ *
+ * @param h The channel handler receiving the message
+ * @param vendorMessage The vendor message to parse.
+ * @return The role in the message if the message is a Nicira role
+ * reply, null otherwise.
+ * @throws SwitchStateException If the message is a Nicira role reply
+ * but the numeric role value is unknown.
+ */
+ protected Role extractNiciraRoleReply(OFChannelHandler h,
+ OFExperimenter experimenterMsg) throws SwitchStateException {
+ int vendor = (int) experimenterMsg.getExperimenter();
+ if (vendor != 0x2320) {
+ return null;
+ }
+ OFNiciraControllerRoleReply nrr =
+ (OFNiciraControllerRoleReply) experimenterMsg;
+
+ Role role = null;
+ OFNiciraControllerRole ncr = nrr.getRole();
+ switch(ncr) {
+ case ROLE_MASTER:
+ role = Role.MASTER;
+ break;
+ case ROLE_OTHER:
+ role = Role.EQUAL;
+ break;
+ case ROLE_SLAVE:
+ role = Role.SLAVE;
+ break;
+ default: //handled below
+ }
+
+ if (role == null) {
+ String msg = String.format("Switch: [%s], State: [%s], "
+ + "received NX_ROLE_REPLY with invalid role "
+ + "value %s",
+ h.getSwitchInfoString(),
+ this.toString(),
+ nrr.getRole());
+ throw new SwitchStateException(msg);
+ }
+ return role;
+ }
+
+ /**
+ * Helper class returns role reply information in the format understood
+ * by the controller.
+ */
+ protected static class RoleReplyInfo {
+ private Role role;
+ private U64 genId;
+ private long xid;
+
+ RoleReplyInfo(Role role, U64 genId, long xid) {
+ this.role = role;
+ this.genId = genId;
+ this.xid = xid;
+ }
+ public Role getRole() { return role; }
+ public U64 getGenId() { return genId; }
+ public long getXid() { return xid; }
+ @Override
+ public String toString() {
+ return "[Role:" + role + " GenId:" + genId + " Xid:" + xid + "]";
+ }
+ }
+
+ /**
+ * Extract the role information from an OF1.3 Role Reply Message.
+ * @param h
+ * @param rrmsg
+ * @return RoleReplyInfo object
+ * @throws SwitchStateException
+ */
+ protected RoleReplyInfo extractOFRoleReply(OFChannelHandler h,
+ OFRoleReply rrmsg) throws SwitchStateException {
+ OFControllerRole cr = rrmsg.getRole();
+ Role role = null;
+ switch(cr) {
+ case ROLE_EQUAL:
+ role = Role.EQUAL;
+ break;
+ case ROLE_MASTER:
+ role = Role.MASTER;
+ break;
+ case ROLE_SLAVE:
+ role = Role.SLAVE;
+ break;
+ case ROLE_NOCHANGE: // switch should send current role
+ default:
+ String msg = String.format("Unknown controller role %s "
+ + "received from switch %s", cr, h.sw);
+ throw new SwitchStateException(msg);
+ }
+
+ return new RoleReplyInfo(role, rrmsg.getGenerationId(), rrmsg.getXid());
+ }
+
+ /**
+ * Handles all pending port status messages before a switch is declared
+ * activated in MASTER or EQUAL role. Note that since this handling
+ * precedes the activation (and therefore notification to IOFSwitchListerners)
+ * the changes to ports will already be visible once the switch is
+ * activated. As a result, no notifications are sent out for these
+ * pending portStatus messages.
+ * @param h
+ * @throws SwitchStateException
+ */
+ protected void handlePendingPortStatusMessages(OFChannelHandler h) {
+ try {
+ handlePendingPortStatusMessages(h, 0);
+ } catch (SwitchStateException e) {
+ log.error(e.getMessage());
+ }
+ }
+
+ private void handlePendingPortStatusMessages(OFChannelHandler h, int index)
+ throws SwitchStateException {
+ if (h.sw == null) {
+ String msg = "State machine error: switch is null. Should never " +
+ "happen";
+ throw new SwitchStateException(msg);
+ }
+ ArrayList<OFPortStatus> temp = new ArrayList<OFPortStatus>();
+ for (OFPortStatus ps: h.pendingPortStatusMsg) {
+ temp.add(ps);
+ handlePortStatusMessage(h, ps, false);
+ }
+ temp.clear();
+ // expensive but ok - we don't expect too many port-status messages
+ // note that we cannot use clear(), because of the reasons below
+ h.pendingPortStatusMsg.removeAll(temp);
+ // the iterator above takes a snapshot of the list - so while we were
+ // dealing with the pending port-status messages, we could have received
+ // newer ones. Handle them recursively, but break the recursion after
+ // five steps to avoid an attack.
+ if (!h.pendingPortStatusMsg.isEmpty() && ++index < 5) {
+ handlePendingPortStatusMessages(h, index);
+ }
+ }
+
+ /**
+ * Handle a port status message.
+ *
+ * Handle a port status message by updating the port maps in the
+ * IOFSwitch instance and notifying Controller about the change so
+ * it can dispatch a switch update.
+ *
+ * @param h The OFChannelHhandler that received the message
+ * @param m The PortStatus message we received
+ * @param doNotify if true switch port changed events will be
+ * dispatched
+ * @throws SwitchStateException
+ *
+ */
+ protected void handlePortStatusMessage(OFChannelHandler h, OFPortStatus m,
+ boolean doNotify) throws SwitchStateException {
+ if (h.sw == null) {
+ String msg = getSwitchStateMessage(h, m,
+ "State machine error: switch is null. Should never " +
+ "happen");
+ throw new SwitchStateException(msg);
+ }
+
+ Collection<PortChangeEvent> changes = h.sw.processOFPortStatus(m);
+ if (doNotify) {
+ for (PortChangeEvent ev: changes) {
+ h.controller.notifyPortChanged(h.sw.getId(), ev.port, ev.type);
+ }
+ }
+ }
+
+ /**
+ * Checks if the role received (from the role-reply msg) is different
+ * from the existing role in the IOFSwitch object for this controller.
+ * If so, it transitions the controller to the new role. Note that
+ * the caller should have already verified that the role-reply msg
+ * received was in response to a role-request msg sent out by this
+ * controller after hearing from the registry service.
+ *
+ * @param h the ChannelHandler that received the message
+ * @param role the role in the recieved role reply message
+ */
+ protected void checkAndSetRoleTransition(OFChannelHandler h, Role role) {
+ // we received a role-reply in response to a role message
+ // sent after hearing from the registry service. It is
+ // possible that the role of this controller instance for
+ // this switch has changed:
+ // for 1.0 switch: from MASTER to SLAVE
+ // for 1.3 switch: from MASTER to EQUAL
+ if ((h.sw.getRole() == Role.MASTER && role == Role.SLAVE) ||
+ (h.sw.getRole() == Role.MASTER && role == Role.EQUAL)) {
+ // the mastership has changed
+ h.sw.setRole(role);
+ h.setState(EQUAL);
+ h.controller.transitionToEqualSwitch(h.sw.getId());
+ return;
+ }
+
+ // or for both 1.0 and 1.3 switches from EQUAL to MASTER.
+ // note that for 1.0, even though we mean SLAVE,
+ // internally we call the role EQUAL.
+ if (h.sw.getRole() == Role.EQUAL && role == Role.MASTER) {
+ // the mastership has changed
+ h.sw.setRole(role);
+ h.setState(MASTER);
+ h.controller.transitionToMasterSwitch(h.sw.getId());
+ return;
+ }
+ }
+
+ /**
+ * Process an OF message received on the channel and
+ * update state accordingly.
+ *
+ * The main "event" of the state machine. Process the received message,
+ * send follow up message if required and update state if required.
+ *
+ * Switches on the message type and calls more specific event handlers
+ * for each individual OF message type. If we receive a message that
+ * is supposed to be sent from a controller to a switch we throw
+ * a SwitchStateExeption.
+ *
+ * The more specific handlers can also throw SwitchStateExceptions
+ *
+ * @param h The OFChannelHandler that received the message
+ * @param m The message we received.
+ * @throws SwitchStateException
+ * @throws IOException
+ */
+ void processOFMessage(OFChannelHandler h, OFMessage m)
+ throws IOException, SwitchStateException {
+ h.roleChanger.checkTimeout();
+ switch(m.getType()) {
+ case HELLO:
+ processOFHello(h, (OFHello) m);
+ break;
+ case BARRIER_REPLY:
+ processOFBarrierReply(h, (OFBarrierReply) m);
+ break;
+ case ECHO_REPLY:
+ processOFEchoReply(h, (OFEchoReply) m);
+ break;
+ case ECHO_REQUEST:
+ processOFEchoRequest(h, (OFEchoRequest) m);
+ break;
+ case ERROR:
+ processOFError(h, (OFErrorMsg) m);
+ break;
+ case FEATURES_REPLY:
+ processOFFeaturesReply(h, (OFFeaturesReply) m);
+ break;
+ case FLOW_REMOVED:
+ processOFFlowRemoved(h, (OFFlowRemoved) m);
+ break;
+ case GET_CONFIG_REPLY:
+ processOFGetConfigReply(h, (OFGetConfigReply) m);
+ break;
+ case PACKET_IN:
+ processOFPacketIn(h, (OFPacketIn) m);
+ break;
+ case PORT_STATUS:
+ processOFPortStatus(h, (OFPortStatus) m);
+ break;
+ case QUEUE_GET_CONFIG_REPLY:
+ processOFQueueGetConfigReply(h, (OFQueueGetConfigReply) m);
+ break;
+ case STATS_REPLY: // multipart_reply in 1.3
+ processOFStatisticsReply(h, (OFStatsReply) m);
+ break;
+ case EXPERIMENTER:
+ processOFExperimenter(h, (OFExperimenter) m);
+ break;
+ case ROLE_REPLY:
+ processOFRoleReply(h, (OFRoleReply) m);
+ break;
+ case GET_ASYNC_REPLY:
+ processOFGetAsyncReply(h, (OFAsyncGetReply) m);
+ break;
+
+ // The following messages are sent to switches. The controller
+ // should never receive them
+ case SET_CONFIG:
+ case GET_CONFIG_REQUEST:
+ case PACKET_OUT:
+ case PORT_MOD:
+ case QUEUE_GET_CONFIG_REQUEST:
+ case BARRIER_REQUEST:
+ case STATS_REQUEST: // multipart request in 1.3
+ case FEATURES_REQUEST:
+ case FLOW_MOD:
+ case GROUP_MOD:
+ case TABLE_MOD:
+ case GET_ASYNC_REQUEST:
+ case SET_ASYNC:
+ case METER_MOD:
+ default:
+ illegalMessageReceived(h, m);
+ break;
+ }
+ }
+
+ /*-----------------------------------------------------------------
+ * Default implementation for message handlers in any state.
+ *
+ * Individual states must override these if they want a behavior
+ * that differs from the default.
+ *
+ * In general, these handlers simply ignore the message and do
+ * nothing.
+ *
+ * There are some exceptions though, since some messages really
+ * are handled the same way in every state (e.g., ECHO_REQUST) or
+ * that are only valid in a single state (e.g., HELLO, GET_CONFIG_REPLY
+ -----------------------------------------------------------------*/
+
+ void processOFHello(OFChannelHandler h, OFHello m)
+ throws IOException, SwitchStateException {
+ // we only expect hello in the WAIT_HELLO state
+ illegalMessageReceived(h, m);
+ }
+
+ void processOFBarrierReply(OFChannelHandler h, OFBarrierReply m)
+ throws IOException {
+ // Silently ignore.
+ }
+
+ void processOFEchoRequest(OFChannelHandler h, OFEchoRequest m)
+ throws IOException {
+ if (h.ofVersion == null) {
+ log.error("No OF version set for {}. Not sending Echo REPLY",
+ h.channel.getRemoteAddress());
+ return;
+ }
+ OFFactory factory = (h.ofVersion == OFVersion.OF_13) ?
+ h.controller.getOFMessageFactory13() : h.controller.getOFMessageFactory10();
+ OFEchoReply reply = factory
+ .buildEchoReply()
+ .setXid(m.getXid())
+ .setData(m.getData())
+ .build();
+ h.channel.write(Collections.singletonList(reply));
+ }
+
+ void processOFEchoReply(OFChannelHandler h, OFEchoReply m)
+ throws IOException {
+ // Do nothing with EchoReplies !!
+ }
+
+ // no default implementation for OFError
+ // every state must override it
+ abstract void processOFError(OFChannelHandler h, OFErrorMsg m)
+ throws IOException, SwitchStateException;
+
+
+ void processOFFeaturesReply(OFChannelHandler h, OFFeaturesReply m)
+ throws IOException, SwitchStateException {
+ unhandledMessageReceived(h, m);
+ }
+
+ void processOFFlowRemoved(OFChannelHandler h, OFFlowRemoved m)
+ throws IOException {
+ unhandledMessageReceived(h, m);
+ }
+
+ void processOFGetConfigReply(OFChannelHandler h, OFGetConfigReply m)
+ throws IOException, SwitchStateException {
+ // we only expect config replies in the WAIT_CONFIG_REPLY state
+ illegalMessageReceived(h, m);
+ }
+
+ void processOFPacketIn(OFChannelHandler h, OFPacketIn m)
+ throws IOException {
+ unhandledMessageReceived(h, m);
+ }
+
+ // no default implementation. Every state needs to handle it.
+ abstract void processOFPortStatus(OFChannelHandler h, OFPortStatus m)
+ throws IOException, SwitchStateException;
+
+ void processOFQueueGetConfigReply(OFChannelHandler h,
+ OFQueueGetConfigReply m)
+ throws IOException {
+ unhandledMessageReceived(h, m);
+ }
+
+ void processOFStatisticsReply(OFChannelHandler h, OFStatsReply m)
+ throws IOException, SwitchStateException {
+ unhandledMessageReceived(h, m);
+ }
+
+ void processOFExperimenter(OFChannelHandler h, OFExperimenter m)
+ throws IOException, SwitchStateException {
+ // TODO: it might make sense to parse the vendor message here
+ // into the known vendor messages we support and then call more
+ // specific event handlers
+ unhandledMessageReceived(h, m);
+ }
+
+ void processOFRoleReply(OFChannelHandler h, OFRoleReply m)
+ throws SwitchStateException, IOException {
+ unhandledMessageReceived(h, m);
+ }
+
+ void processOFGetAsyncReply(OFChannelHandler h,
+ OFAsyncGetReply m) {
+ unhandledMessageReceived(h, m);
+ }
+
+ void handleUnsentRoleMessage(OFChannelHandler h, Role role,
+ RoleRecvStatus expectation) throws IOException {
+ // do nothing in most states
+ }
+ }
+
+
+
+ //*************************
+ // Channel handler methods
+ //*************************
+
+ @Override
+ @LogMessageDoc(message = "New switch connection from {ip address}",
+ explanation = "A new switch has connected from the "
+ + "specified IP address")
+ public void channelConnected(ChannelHandlerContext ctx,
+ ChannelStateEvent e) throws Exception {
+ counters.switchConnected.updateCounterWithFlush();
+ channel = e.getChannel();
+ log.info("New switch connection from {}",
+ channel.getRemoteAddress());
+ sendHandshakeHelloMessage();
+ setState(ChannelState.WAIT_HELLO);
+ }
+
+ @Override
+ @LogMessageDoc(message = "Disconnected switch {switch information}",
+ explanation = "The specified switch has disconnected.")
+ public void channelDisconnected(ChannelHandlerContext ctx,
+ ChannelStateEvent e) throws Exception {
+ log.info("Switch disconnected callback for sw:{}. Cleaning up ...",
+ getSwitchInfoString());
+ if (thisdpid != 0) {
+ if (!duplicateDpidFound) {
+ // if the disconnected switch (on this ChannelHandler)
+ // was not one with a duplicate-dpid, it is safe to remove all
+ // state for it at the controller. Notice that if the disconnected
+ // switch was a duplicate-dpid, calling the method below would clear
+ // all state for the original switch (with the same dpid),
+ // which we obviously don't want.
+ controller.removeConnectedSwitch(thisdpid);
+ } else {
+ // A duplicate was disconnected on this ChannelHandler,
+ // this is the same switch reconnecting, but the original state was
+ // not cleaned up - XXX check liveness of original ChannelHandler
+ duplicateDpidFound = Boolean.FALSE;
+ }
+ } else {
+ log.warn("no dpid in channelHandler registered for "
+ + "disconnected switch {}", getSwitchInfoString());
+ }
+ }
+
+ @Override
+ @LogMessageDocs({
+ @LogMessageDoc(level = "ERROR",
+ message = "Disconnecting switch {switch} due to read timeout",
+ explanation = "The connected switch has failed to send any "
+ + "messages or respond to echo requests",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Disconnecting switch {switch}: failed to "
+ + "complete handshake",
+ explanation = "The switch did not respond correctly "
+ + "to handshake messages",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Disconnecting switch {switch} due to IO Error: {}",
+ explanation = "There was an error communicating with the switch",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Disconnecting switch {switch} due to switch "
+ + "state error: {error}",
+ explanation = "The switch sent an unexpected message",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Disconnecting switch {switch} due to "
+ + "message parse failure",
+ explanation = "Could not parse a message from the switch",
+ recommendation = LogMessageDoc.CHECK_SWITCH),
+ @LogMessageDoc(level = "ERROR",
+ message = "Terminating controller due to storage exception",
+ explanation = Controller.ERROR_DATABASE,
+ recommendation = LogMessageDoc.CHECK_CONTROLLER),
+ @LogMessageDoc(level = "ERROR",
+ message = "Could not process message: queue full",
+ explanation = "OpenFlow messages are arriving faster than "
+ + "the controller can process them.",
+ recommendation = LogMessageDoc.CHECK_CONTROLLER),
+ @LogMessageDoc(level = "ERROR",
+ message = "Error while processing message "
+ + "from switch {switch} {cause}",
+ explanation = "An error occurred processing the switch message",
+ recommendation = LogMessageDoc.GENERIC_ACTION)
+ })
+ public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
+ throws Exception {
+ if (e.getCause() instanceof ReadTimeoutException) {
+ // switch timeout
+ log.error("Disconnecting switch {} due to read timeout",
+ getSwitchInfoString());
+ counters.switchDisconnectReadTimeout.updateCounterWithFlush();
+ ctx.getChannel().close();
+ } else if (e.getCause() instanceof HandshakeTimeoutException) {
+ log.error("Disconnecting switch {}: failed to complete handshake",
+ getSwitchInfoString());
+ counters.switchDisconnectHandshakeTimeout.updateCounterWithFlush();
+ ctx.getChannel().close();
+ } else if (e.getCause() instanceof ClosedChannelException) {
+ log.debug("Channel for sw {} already closed", getSwitchInfoString());
+ } else if (e.getCause() instanceof IOException) {
+ log.error("Disconnecting switch {} due to IO Error: {}",
+ getSwitchInfoString(), e.getCause().getMessage());
+ if (log.isDebugEnabled()) {
+ // still print stack trace if debug is enabled
+ log.debug("StackTrace for previous Exception: ", e.getCause());
+ }
+ counters.switchDisconnectIOError.updateCounterWithFlush();
+ ctx.getChannel().close();
+ } else if (e.getCause() instanceof SwitchStateException) {
+ log.error("Disconnecting switch {} due to switch state error: {}",
+ getSwitchInfoString(), e.getCause().getMessage());
+ if (log.isDebugEnabled()) {
+ // still print stack trace if debug is enabled
+ log.debug("StackTrace for previous Exception: ", e.getCause());
+ }
+ counters.switchDisconnectSwitchStateException.updateCounterWithFlush();
+ ctx.getChannel().close();
+ } else if (e.getCause() instanceof OFParseError) {
+ log.error("Disconnecting switch "
+ + getSwitchInfoString() +
+ " due to message parse failure",
+ e.getCause());
+ counters.switchDisconnectParseError.updateCounterWithFlush();
+ ctx.getChannel().close();
+ } else if (e.getCause() instanceof RejectedExecutionException) {
+ log.warn("Could not process message: queue full");
+ counters.rejectedExecutionException.updateCounterWithFlush();
+ } else {
+ log.error("Error while processing message from switch "
+ + getSwitchInfoString()
+ + "state " + this.state, e.getCause());
+ counters.switchDisconnectOtherException.updateCounterWithFlush();
+ ctx.getChannel().close();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getSwitchInfoString();
+ }
+
+ @Override
+ public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e)
+ throws Exception {
+ OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
+ OFMessage m = factory.buildEchoRequest().build();
+ log.info("Sending Echo Request on idle channel: {}",
+ e.getChannel().getPipeline().getLast().toString());
+ e.getChannel().write(Collections.singletonList(m));
+ // XXX S some problems here -- echo request has no transaction id, and
+ // echo reply is not correlated to the echo request.
+ }
+
+ @Override
+ public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
+ throws Exception {
+ if (e.getMessage() instanceof List) {
+ @SuppressWarnings("unchecked")
+ List<OFMessage> msglist = (List<OFMessage>) e.getMessage();
+
+
+ for (OFMessage ofm : msglist) {
+ counters.messageReceived.updateCounterNoFlush();
+ // Do the actual packet processing
+ state.processOFMessage(this, ofm);
+ }
+ } else {
+ counters.messageReceived.updateCounterNoFlush();
+ state.processOFMessage(this, (OFMessage) e.getMessage());
+ }
+ }
+
+
+
+ //*************************
+ // Channel utility methods
+ //*************************
+
+ /**
+ * Is this a state in which the handshake has completed?
+ * @return true if the handshake is complete
+ */
+ public boolean isHandshakeComplete() {
+ return this.state.isHandshakeComplete();
+ }
+
+ private void dispatchMessage(OFMessage m) throws IOException {
+ sw.handleMessage(m);
+ }
+
+ /**
+ * Return a string describing this switch based on the already available
+ * information (DPID and/or remote socket).
+ * @return
+ */
+ private String getSwitchInfoString() {
+ if (sw != null) {
+ return sw.toString();
+ }
+ String channelString;
+ if (channel == null || channel.getRemoteAddress() == null) {
+ channelString = "?";
+ } else {
+ channelString = channel.getRemoteAddress().toString();
+ }
+ String dpidString;
+ if (featuresReply == null) {
+ dpidString = "?";
+ } else {
+ dpidString = featuresReply.getDatapathId().toString();
+ }
+ return String.format("[%s DPID[%s]]", channelString, dpidString);
+ }
+
+ /**
+ * Update the channels state. Only called from the state machine.
+ * TODO: enforce restricted state transitions
+ * @param state
+ */
+ private void setState(ChannelState state) {
+ this.state = state;
+ }
+
+ /**
+ * Send hello message to the switch using the handshake transactions ids.
+ * @throws IOException
+ */
+ private void sendHandshakeHelloMessage() throws IOException {
+ // The OF protocol requires us to start things off by sending the highest
+ // version of the protocol supported.
+
+ // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04)
+ // see Sec. 7.5.1 of the OF1.3.4 spec
+ U32 bitmap = U32.ofRaw(0x00000012);
+ OFHelloElem hem = factory13.buildHelloElemVersionbitmap()
+ .setBitmaps(Collections.singletonList(bitmap))
+ .build();
+ OFMessage.Builder mb = factory13.buildHello()
+ .setXid(this.handshakeTransactionIds--)
+ .setElements(Collections.singletonList(hem));
+ log.info("Sending OF_13 Hello to {}", channel.getRemoteAddress());
+ channel.write(Collections.singletonList(mb.build()));
+ }
+
+ /**
+ * Send featuresRequest msg to the switch using the handshake transactions ids.
+ * @throws IOException
+ */
+ private void sendHandshakeFeaturesRequestMessage() throws IOException {
+ OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
+ OFMessage m = factory.buildFeaturesRequest()
+ .setXid(this.handshakeTransactionIds--)
+ .build();
+ channel.write(Collections.singletonList(m));
+ }
+
+ private void setSwitchRole(Role role) {
+ sw.setRole(role);
+ }
+
+ /**
+ * Send the configuration requests to tell the switch we want full
+ * packets.
+ * @throws IOException
+ */
+ private void sendHandshakeSetConfig() throws IOException {
+ OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
+ //log.debug("Sending CONFIG_REQUEST to {}", channel.getRemoteAddress());
+ List<OFMessage> msglist = new ArrayList<OFMessage>(3);
+
+ // Ensure we receive the full packet via PacketIn
+ // FIXME: We don't set the reassembly flags.
+ OFSetConfig sc = factory
+ .buildSetConfig()
+ .setMissSendLen((short) 0xffff)
+ .setXid(this.handshakeTransactionIds--)
+ .build();
+ msglist.add(sc);
+
+ // Barrier
+ OFBarrierRequest br = factory
+ .buildBarrierRequest()
+ .setXid(this.handshakeTransactionIds--)
+ .build();
+ msglist.add(br);
+
+ // Verify (need barrier?)
+ OFGetConfigRequest gcr = factory
+ .buildGetConfigRequest()
+ .setXid(this.handshakeTransactionIds--)
+ .build();
+ msglist.add(gcr);
+ channel.write(msglist);
+ }
+
+ /**
+ * send a description state request.
+ * @throws IOException
+ */
+ private void sendHandshakeDescriptionStatsRequest() throws IOException {
+ // Get Description to set switch-specific flags
+ OFFactory factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
+ OFDescStatsRequest dreq = factory
+ .buildDescStatsRequest()
+ .setXid(handshakeTransactionIds--)
+ .build();
+ channel.write(Collections.singletonList(dreq));
+ }
+
+ private void sendHandshakeOFPortDescRequest() throws IOException {
+ // Get port description for 1.3 switch
+ OFPortDescStatsRequest preq = factory13
+ .buildPortDescStatsRequest()
+ .setXid(handshakeTransactionIds--)
+ .build();
+ channel.write(Collections.singletonList(preq));
+ }
+
+ ChannelState getStateForTesting() {
+ return state;
+ }
+
+ void useRoleChangerWithOtherTimeoutForTesting(long roleTimeoutMs) {
+ roleChanger = new RoleChanger(roleTimeoutMs);
+ }
+
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFMessageDecoder.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFMessageDecoder.java
new file mode 100644
index 0000000..ff6fbf5
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFMessageDecoder.java
@@ -0,0 +1,56 @@
+/**
+ * Copyright 2011, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.internal;
+
+
+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.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFMessageReader;
+
+/**
+ * Decode an openflow message from a Channel, for use in a netty pipeline.
+ */
+public class OFMessageDecoder extends FrameDecoder {
+
+ @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 corrupted frames
+ return null;
+ }
+
+ // Note that a single call to decode results in reading a single
+ // OFMessage from the channel buffer, which is passed on to, and processed
+ // by, the controller (in OFChannelHandler).
+ // This is different from earlier behavior (with the original openflowj),
+ // where we parsed all the messages in the buffer, before passing on
+ // a list of the parsed messages to the controller.
+ // The performance *may or may not* not be as good as before.
+ OFMessageReader<OFMessage> reader = OFFactories.getGenericReader();
+ OFMessage message = reader.readFrom(buffer);
+
+ return message;
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFMessageEncoder.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFMessageEncoder.java
new file mode 100644
index 0000000..86933fc
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OFMessageEncoder.java
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2011, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.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.projectfloodlight.openflow.protocol.OFMessage;
+
+
+/**
+ * Encode an openflow message for output into a ChannelBuffer, for use in a
+ * netty pipeline.
+ */
+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;
+ /* XXX S can't get length of OFMessage in loxigen's openflowj??
+ int size = 0;
+ for (OFMessage ofm : msglist) {
+ size += ofm.getLengthU();
+ }*/
+
+ ChannelBuffer buf = ChannelBuffers.dynamicBuffer();
+
+ for (OFMessage ofm : msglist) {
+ ofm.writeTo(buf);
+ }
+ return buf;
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OpenflowPipelineFactory.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OpenflowPipelineFactory.java
new file mode 100644
index 0000000..30f0287
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/OpenflowPipelineFactory.java
@@ -0,0 +1,78 @@
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson, Stanford University
+*
+* Licensed under the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License. You may obtain
+* a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+**/
+
+package net.onrc.onos.of.ctl.internal;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelPipelineFactory;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.handler.execution.ExecutionHandler;
+import org.jboss.netty.handler.timeout.IdleStateHandler;
+import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
+import org.jboss.netty.util.ExternalResourceReleasable;
+import org.jboss.netty.util.HashedWheelTimer;
+import org.jboss.netty.util.Timer;
+
+/**
+ * Creates a ChannelPipeline for a server-side openflow channel.
+ */
+public class OpenflowPipelineFactory
+ implements ChannelPipelineFactory, ExternalResourceReleasable {
+
+ protected Controller controller;
+ protected ThreadPoolExecutor pipelineExecutor;
+ protected Timer timer;
+ protected IdleStateHandler idleHandler;
+ protected ReadTimeoutHandler readTimeoutHandler;
+
+ public OpenflowPipelineFactory(Controller controller,
+ ThreadPoolExecutor pipelineExecutor) {
+ super();
+ this.controller = controller;
+ this.pipelineExecutor = pipelineExecutor;
+ this.timer = new HashedWheelTimer();
+ this.idleHandler = new IdleStateHandler(timer, 20, 25, 0);
+ this.readTimeoutHandler = new ReadTimeoutHandler(timer, 30);
+ }
+
+ @Override
+ public ChannelPipeline getPipeline() throws Exception {
+ OFChannelHandler handler = new OFChannelHandler(controller);
+
+ ChannelPipeline pipeline = Channels.pipeline();
+ pipeline.addLast("ofmessagedecoder", new OFMessageDecoder());
+ pipeline.addLast("ofmessageencoder", new OFMessageEncoder());
+ pipeline.addLast("idle", idleHandler);
+ pipeline.addLast("timeout", readTimeoutHandler);
+ // XXX S ONOS: was 15 increased it to fix Issue #296
+ pipeline.addLast("handshaketimeout",
+ new HandshakeTimeoutHandler(handler, timer, 60));
+ if (pipelineExecutor != null) {
+ pipeline.addLast("pipelineExecutor",
+ new ExecutionHandler(pipelineExecutor));
+ }
+ pipeline.addLast("handler", handler);
+ return pipeline;
+ }
+
+ @Override
+ public void releaseExternalResources() {
+ timer.stop();
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeAlreadyStarted.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeAlreadyStarted.java
new file mode 100644
index 0000000..92c673c
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeAlreadyStarted.java
@@ -0,0 +1,14 @@
+package net.onrc.onos.of.ctl.internal;
+
+/**
+ * Thrown when IOFSwitch.startDriverHandshake() is called more than once.
+ *
+ */
+public class SwitchDriverSubHandshakeAlreadyStarted extends
+ SwitchDriverSubHandshakeException {
+ private static final long serialVersionUID = -5491845708752443501L;
+
+ public SwitchDriverSubHandshakeAlreadyStarted() {
+ super();
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeCompleted.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeCompleted.java
new file mode 100644
index 0000000..1600854
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeCompleted.java
@@ -0,0 +1,19 @@
+package net.onrc.onos.of.ctl.internal;
+
+import org.projectfloodlight.openflow.protocol.OFMessage;
+
+
+/**
+ * Indicates that a message was passed to a switch driver's subhandshake
+ * handling code but the driver has already completed the sub-handshake.
+ *
+ */
+public class SwitchDriverSubHandshakeCompleted
+ extends SwitchDriverSubHandshakeException {
+ private static final long serialVersionUID = -8817822245846375995L;
+
+ public SwitchDriverSubHandshakeCompleted(OFMessage m) {
+ super("Sub-Handshake is already complete but received message "
+ + m.getType());
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeException.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeException.java
new file mode 100644
index 0000000..c7d68f3
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeException.java
@@ -0,0 +1,26 @@
+package net.onrc.onos.of.ctl.internal;
+
+/**
+ * Base class for exception thrown by switch driver sub-handshake processing.
+ *
+ */
+public class SwitchDriverSubHandshakeException extends RuntimeException {
+ private static final long serialVersionUID = -6257836781419604438L;
+
+ protected SwitchDriverSubHandshakeException() {
+ super();
+ }
+
+ protected SwitchDriverSubHandshakeException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+ protected SwitchDriverSubHandshakeException(String arg0) {
+ super(arg0);
+ }
+
+ protected SwitchDriverSubHandshakeException(Throwable arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeNotStarted.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeNotStarted.java
new file mode 100644
index 0000000..d568cc6
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeNotStarted.java
@@ -0,0 +1,15 @@
+package net.onrc.onos.of.ctl.internal;
+
+/**
+ * Thrown when a switch driver's sub-handshake has not been started but an
+ * operation requiring the sub-handshake has been attempted.
+ *
+ */
+public class SwitchDriverSubHandshakeNotStarted extends
+ SwitchDriverSubHandshakeException {
+ private static final long serialVersionUID = -5491845708752443501L;
+
+ public SwitchDriverSubHandshakeNotStarted() {
+ super();
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeStateException.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeStateException.java
new file mode 100644
index 0000000..6091a86
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchDriverSubHandshakeStateException.java
@@ -0,0 +1,15 @@
+package net.onrc.onos.of.ctl.internal;
+
+/**
+ * Thrown when a switch driver's sub-handshake state-machine receives an
+ * unexpected OFMessage and/or is in an invald state.
+ *
+ */
+public class SwitchDriverSubHandshakeStateException extends
+ SwitchDriverSubHandshakeException {
+ private static final long serialVersionUID = -8249926069195147051L;
+
+ public SwitchDriverSubHandshakeStateException(String msg) {
+ super(msg);
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchStateException.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchStateException.java
new file mode 100644
index 0000000..e51b60d
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/internal/SwitchStateException.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2011, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.internal;
+
+/**
+ * This exception indicates an error or unexpected message during
+ * message handling. E.g., if an OFMessage is received that is illegal or
+ * unexpected given the current handshake state.
+ *
+ * We don't allow wrapping other exception in a switch state exception. We
+ * only log the SwitchStateExceptions message so the causing exceptions
+ * stack trace is generally not available.
+ *
+ */
+public class SwitchStateException extends Exception {
+
+ private static final long serialVersionUID = 9153954512470002631L;
+
+ public SwitchStateException() {
+ super();
+ }
+
+ public SwitchStateException(String arg0, Throwable arg1) {
+ super(arg0, arg1);
+ }
+
+ public SwitchStateException(String arg0) {
+ super(arg0);
+ }
+
+ public SwitchStateException(Throwable arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/ControllerRegistryEntry.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/ControllerRegistryEntry.java
new file mode 100644
index 0000000..2472f64
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/ControllerRegistryEntry.java
@@ -0,0 +1,66 @@
+package net.onrc.onos.of.ctl.registry;
+
+
+
+public class ControllerRegistryEntry implements Comparable<ControllerRegistryEntry> {
+ //
+ // TODO: Refactor the implementation and decide whether controllerId
+ // is needed. If "yes", we might need to consider it inside the
+ // compareTo(), equals() and hashCode() implementations.
+ //
+ private final String controllerId;
+ private final int sequenceNumber;
+
+ public ControllerRegistryEntry(String controllerId, int sequenceNumber) {
+ this.controllerId = controllerId;
+ this.sequenceNumber = sequenceNumber;
+ }
+
+ public String getControllerId() {
+ return controllerId;
+ }
+
+ /**
+ * Compares this object with the specified object for order.
+ * NOTE: the test is based on ControllerRegistryEntry sequence numbers,
+ * and doesn't include the controllerId.
+ *
+ * @param o the object to be compared.
+ * @return a negative integer, zero, or a positive integer as this object
+ * is less than, equal to, or greater than the specified object.
+ */
+ @Override
+ public int compareTo(ControllerRegistryEntry o) {
+ return this.sequenceNumber - o.sequenceNumber;
+ }
+
+ /**
+ * Test whether some other object is "equal to" this one.
+ * NOTE: the test is based on ControllerRegistryEntry sequence numbers,
+ * and doesn't include the controllerId.
+ *
+ * @param obj the reference object with which to compare.
+ * @return true if this object is the same as the obj argument; false
+ * otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ControllerRegistryEntry) {
+ ControllerRegistryEntry other = (ControllerRegistryEntry) obj;
+ return this.sequenceNumber == other.sequenceNumber;
+ }
+ return false;
+ }
+
+ /**
+ * Get the hash code for the object.
+ * NOTE: the computation is based on ControllerRegistryEntry sequence
+ * numbers, and doesn't include the controller ID.
+ *
+ * @return a hash code value for this object.
+ */
+ @Override
+ public int hashCode() {
+ return Integer.valueOf(this.sequenceNumber).hashCode();
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/IControllerRegistry.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/IControllerRegistry.java
new file mode 100644
index 0000000..0b67338
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/IControllerRegistry.java
@@ -0,0 +1,155 @@
+package net.onrc.onos.of.ctl.registry;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import net.onrc.onos.of.ctl.util.InstanceId;
+
+/**
+ * A registry service that allows ONOS to register controllers and switches in a
+ * way that is global to the entire ONOS cluster. The registry is the arbiter
+ * for allowing controllers to control switches.
+ * <p/>
+ * The OVS/OF1.{2,3} fault tolerance model is a switch connects to multiple
+ * controllers, and the controllers send role requests to tell the switch their
+ * role in controlling the switch.
+ * <p/>
+ * The ONOS fault tolerance model allows only a single controller to have
+ * control of a switch (MASTER role) at once. Controllers therefore need a
+ * mechanism that enables them to decide who should control a each switch. The
+ * registry service provides this mechanism.
+ */
+public interface IControllerRegistry {
+
+ /**
+ * Callback interface for control change events.
+ */
+ public interface ControlChangeCallback {
+ /**
+ * Called whenever the control changes from the point of view of the
+ * registry. The callee can check whether they have control or not using
+ * the hasControl parameter.
+ *
+ * @param dpid The switch that control has changed for
+ * @param hasControl Whether the listener now has control or not
+ */
+ void controlChanged(long dpid, boolean hasControl);
+ }
+
+ /**
+ * Request for control of a switch. This method does not block. When control
+ * for a switch changes, the controlChanged method on the callback object
+ * will be called. This happens any time the control changes while the
+ * request is still active (until releaseControl is called)
+ *
+ * @param dpid Switch to request control for
+ * @param cb Callback that will be used to notify caller of control changes
+ * @throws RegistryException Errors contacting the registry service
+ */
+ public void requestControl(long dpid, ControlChangeCallback cb)
+ throws RegistryException;
+
+ /**
+ * Stop trying to take control of a switch. This removes the entry for this
+ * controller requesting this switch in the registry. If the controller had
+ * control when this is called, another controller will now gain control of
+ * the switch. This call doesn't block.
+ *
+ * @param dpid Switch to release control of
+ */
+ public void releaseControl(long dpid);
+
+ /**
+ * Check whether the controller has control of the switch This call doesn't
+ * block.
+ *
+ * @param dpid Switch to check control of
+ * @return true if controller has control of the switch.
+ */
+ public boolean hasControl(long dpid);
+
+ /**
+ * Check whether this instance is the leader for the cluster. This call
+ * doesn't block.
+ *
+ * @return true if the instance is the leader for the cluster, otherwise
+ * false.
+ */
+ public boolean isClusterLeader();
+
+ /**
+ * Gets the unique ID used to identify this ONOS instance in the cluster.
+ *
+ * @return Instance ID.
+ */
+ public InstanceId getOnosInstanceId();
+
+ /**
+ * Register a controller to the ONOS cluster. Must be called before the
+ * registry can be used to take control of any switches.
+ *
+ * @param controllerId A unique string ID identifying this controller in the
+ * cluster
+ * @throws RegistryException for errors connecting to registry service,
+ * controllerId already registered
+ */
+ public void registerController(String controllerId)
+ throws RegistryException;
+
+ /**
+ * Get all controllers in the cluster.
+ *
+ * @return Collection of controller IDs
+ * @throws RegistryException on error
+ */
+ public Collection<String> getAllControllers() throws RegistryException;
+
+ /**
+ * Get all switches in the cluster, along with which controller is in
+ * control of them (if any) and any other controllers that have requested
+ * control.
+ *
+ * @return Map of all switches.
+ */
+ public Map<String, List<ControllerRegistryEntry>> getAllSwitches();
+
+ /**
+ * Get the controller that has control of a given switch.
+ *
+ * @param dpid Switch to find controller for
+ * @return controller ID
+ * @throws RegistryException Errors contacting registry service
+ */
+ public String getControllerForSwitch(long dpid) throws RegistryException;
+
+ /**
+ * Get all switches controlled by a given controller.
+ *
+ * @param controllerId ID of the controller
+ * @return Collection of dpids
+ */
+ public Collection<Long> getSwitchesControlledByController(String controllerId);
+
+ /**
+ * Get a unique Id Block.
+ *
+ * @return Id Block.
+ */
+ public IdBlock allocateUniqueIdBlock();
+
+ /**
+ * Get next unique id and retrieve a new range of ids if needed.
+ *
+ * @param range range to use for the identifier
+ * @return Id Block.
+ */
+ public IdBlock allocateUniqueIdBlock(long range);
+
+ /**
+ * Get a globally unique ID.
+ *
+ * @return a globally unique ID.
+ */
+ public long getNextUniqueId();
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/IdBlock.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/IdBlock.java
new file mode 100644
index 0000000..45d3c83
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/IdBlock.java
@@ -0,0 +1,32 @@
+package net.onrc.onos.of.ctl.registry;
+
+public class IdBlock {
+ private final long start;
+ private final long end;
+ private final long size;
+
+ public IdBlock(long start, long end, long size) {
+ this.start = start;
+ this.end = end;
+ this.size = size;
+ }
+
+ public long getStart() {
+ return start;
+ }
+
+ public long getEnd() {
+ return end;
+ }
+
+ public long getSize() {
+ return size;
+ }
+
+ @Override
+ public String toString() {
+ return "IdBlock [start=" + start + ", end=" + end + ", size=" + size
+ + "]";
+ }
+}
+
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/RegistryException.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/RegistryException.java
new file mode 100644
index 0000000..06f5932
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/registry/RegistryException.java
@@ -0,0 +1,15 @@
+package net.onrc.onos.of.ctl.registry;
+
+public class RegistryException extends Exception {
+
+ private static final long serialVersionUID = -8276300722010217913L;
+
+ public RegistryException(String message) {
+ super(message);
+ }
+
+ public RegistryException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/Dpid.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/Dpid.java
new file mode 100644
index 0000000..5544354
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/Dpid.java
@@ -0,0 +1,74 @@
+package net.onrc.onos.of.ctl.util;
+
+import org.projectfloodlight.openflow.util.HexString;
+
+/**
+ * The class representing a network switch DPID.
+ * This class is immutable.
+ */
+public final class Dpid {
+ private static final long UNKNOWN = 0;
+ private final long value;
+
+ /**
+ * Default constructor.
+ */
+ public Dpid() {
+ this.value = Dpid.UNKNOWN;
+ }
+
+ /**
+ * Constructor from a long value.
+ *
+ * @param value the value to use.
+ */
+ public Dpid(long value) {
+ this.value = value;
+ }
+
+ /**
+ * Constructor from a string.
+ *
+ * @param value the value to use.
+ */
+ public Dpid(String value) {
+ this.value = HexString.toLong(value);
+ }
+
+ /**
+ * Get the value of the DPID.
+ *
+ * @return the value of the DPID.
+ */
+ public long value() {
+ return value;
+ }
+
+ /**
+ * Convert the DPID value to a ':' separated hexadecimal string.
+ *
+ * @return the DPID value as a ':' separated hexadecimal string.
+ */
+ @Override
+ public String toString() {
+ return HexString.toHexString(this.value);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Dpid)) {
+ return false;
+ }
+
+ Dpid otherDpid = (Dpid) other;
+
+ return value == otherDpid.value;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 17;
+ hash += 31 * hash + (int) (value ^ value >>> 32);
+ return hash;
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/DummySwitchForTesting.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/DummySwitchForTesting.java
new file mode 100644
index 0000000..a8eabce
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/DummySwitchForTesting.java
@@ -0,0 +1,360 @@
+package net.onrc.onos.of.ctl.util;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import org.jboss.netty.channel.Channel;
+import org.projectfloodlight.openflow.protocol.OFActionType;
+import org.projectfloodlight.openflow.protocol.OFCapabilities;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFPortStatus;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.U64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.onrc.onos.of.ctl.IOFSwitch;
+import net.onrc.onos.of.ctl.Role;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService.CounterException;
+
+public class DummySwitchForTesting implements IOFSwitch {
+
+ protected static final Logger log = LoggerFactory.getLogger(DummySwitchForTesting.class);
+
+ private Channel channel;
+ private boolean connected = false;
+ private OFVersion ofv = OFVersion.OF_10;
+
+ private Collection<OFPortDesc> ports;
+
+ private DatapathId datapathId;
+
+ private Set<OFCapabilities> capabilities;
+
+ private int buffers;
+
+ private byte tables;
+
+ private String stringId;
+
+ private Role role;
+
+ @Override
+ public void disconnectSwitch() {
+ this.channel.close();
+ }
+
+ @Override
+ public void write(OFMessage m) throws IOException {
+ this.channel.write(m);
+
+ }
+
+ @Override
+ public void write(List<OFMessage> msglist) throws IOException {
+ for (OFMessage m : msglist) {
+ this.channel.write(m);
+ }
+
+ }
+
+ @Override
+ public Date getConnectedSince() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int getNextTransactionId() {
+ return 0;
+ }
+
+ @Override
+ public boolean isConnected() {
+ return this.connected;
+ }
+
+ @Override
+ public void setConnected(boolean connected) {
+ this.connected = connected;
+
+ }
+
+ @Override
+ public void flush() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setChannel(Channel channel) {
+ this.channel = channel;
+
+ }
+
+ @Override
+ public long getId() {
+ if (this.stringId == null) {
+ throw new RuntimeException("Features reply has not yet been set");
+ }
+ return this.datapathId.getLong();
+ }
+
+ @Override
+ public String getStringId() {
+ // TODO Auto-generated method stub
+ return "DummySwitch";
+ }
+
+ @Override
+ public int getNumBuffers() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public Set<OFCapabilities> getCapabilities() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public byte getNumTables() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public OFDescStatsReply getSwitchDescription() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void cancelFeaturesReply(int transactionId) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Set<OFActionType> getActions() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setOFVersion(OFVersion version) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public OFVersion getOFVersion() {
+ return this.ofv;
+ }
+
+ @Override
+ public Collection<OFPortDesc> getEnabledPorts() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Collection<Integer> getEnabledPortNumbers() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public OFPortDesc getPort(int portNumber) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public OFPortDesc getPort(String portName) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public OrderedCollection<PortChangeEvent> processOFPortStatus(
+ OFPortStatus ps) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Collection<OFPortDesc> getPorts() {
+ return ports;
+ }
+
+ @Override
+ public boolean portEnabled(int portName) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public OrderedCollection<PortChangeEvent> setPorts(
+ Collection<OFPortDesc> p) {
+ this.ports = p;
+ return null;
+ }
+
+ @Override
+ public Map<Object, Object> getAttributes() {
+ return null;
+ }
+
+ @Override
+ public boolean hasAttribute(String name) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+ return Boolean.FALSE;
+ }
+
+ @Override
+ public void setAttribute(String name, Object value) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Object removeAttribute(String name) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void deliverStatisticsReply(OFMessage reply) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void cancelStatisticsReply(int transactionId) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void cancelAllStatisticsReplies() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Future<List<OFStatsReply>> getStatistics(OFStatsRequest<?> request)
+ throws IOException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void clearAllFlowMods() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Role getRole() {
+ return this.role;
+ }
+
+ @Override
+ public void setRole(Role role) {
+ this.role = role;
+ }
+
+ @Override
+ public U64 getNextGenerationId() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setDebugCounterService(IDebugCounterService debugCounter)
+ throws CounterException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void startDriverHandshake() throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isDriverHandshakeComplete() {
+ return true;
+ }
+
+ @Override
+ public void processDriverHandshakeMessage(OFMessage m) {
+
+ }
+
+ @Override
+ public void setTableFull(boolean isFull) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setFeaturesReply(OFFeaturesReply featuresReply) {
+ if (featuresReply == null) {
+ log.error("Error setting featuresReply for switch: {}", getStringId());
+ return;
+ }
+ this.datapathId = featuresReply.getDatapathId();
+ this.capabilities = featuresReply.getCapabilities();
+ this.buffers = (int) featuresReply.getNBuffers();
+ this.tables = (byte) featuresReply.getNTables();
+ this.stringId = this.datapathId.toString();
+
+ }
+
+ @Override
+ public void setPortDescReply(OFPortDescStatsReply portDescReply) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void handleMessage(OFMessage m) {
+ log.info("Got packet {} but I am dumb so I don't know what to do.", m);
+ }
+
+ @Override
+ public boolean portEnabled(String portName) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public OrderedCollection<PortChangeEvent> comparePorts(
+ Collection<OFPortDesc> p) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/EnumBitmaps.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/EnumBitmaps.java
new file mode 100644
index 0000000..fe6ccc0
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/EnumBitmaps.java
@@ -0,0 +1,149 @@
+package net.onrc.onos.of.ctl.util;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * A utility class to convert between integer based bitmaps for (OpenFlow)
+ * flags and Enum and EnumSet based representations.
+ *
+ * The enum used to represent individual flags needs to implement the
+ * BitmapableEnum interface.
+ *
+ * Example:
+ * {@code
+ * int bitmap = 0x11; // OFPPC_PORT_DOWN | OFPPC_NO_STP
+ * EnumSet<OFPortConfig> s = toEnumSet(OFPortConfig.class, bitmap);
+ * // s will contain OFPPC_PORT_DOWN and OFPPC_NO_STP
+ * }
+ *
+ * {@code
+ * EnumSet<OFPortConfig> s = EnumSet.of(OFPPC_NO_STP, OFPPC_PORT_DOWN);
+ * int bitmap = toBitmap(s); // returns 0x11
+ * }
+ *
+ */
+public final class EnumBitmaps {
+
+
+ private EnumBitmaps() { }
+
+ /**
+ * Enums used to represent individual flags needs to implement this
+ * interface.
+ */
+ public interface BitmapableEnum {
+ /** Return the value in the bitmap that the enum constant represents.
+ * The returned value must have only a single bit set. E.g.,1 << 3
+ */
+ int getValue();
+ }
+
+
+ /**
+ * Convert an integer bitmap to an EnumSet.
+ *
+ * See class description for example
+ * @param type The Enum class to use. Must implement BitmapableEnum
+ * @param bitmap The integer bitmap
+ * @return A newly allocated EnumSet representing the bits set in the
+ * bitmap
+ * @throws NullPointerException if type is null
+ * @throws IllegalArgumentException if any enum constant from type has
+ * more than one bit set.
+ * @throws IllegalArgumentException if the bitmap has any bits set not
+ * represented by an enum constant.
+ */
+ public static <E extends Enum<E> & BitmapableEnum>
+ EnumSet<E> toEnumSet(Class<E> type, int bitmap) {
+ if (type == null) {
+ throw new NullPointerException("Given enum type must not be null");
+ }
+ EnumSet<E> s = EnumSet.noneOf(type);
+ // allSetBitmap will eventually have all valid bits for the given
+ // type set.
+ int allSetBitmap = 0;
+ for (E element: type.getEnumConstants()) {
+ if (Integer.bitCount(element.getValue()) != 1) {
+ String msg = String.format("The %s (%x) constant of the " +
+ "enum %s is supposed to represent a bitmap entry but " +
+ "has more than one bit set.",
+ element.toString(), element.getValue(), type.getName());
+ throw new IllegalArgumentException(msg);
+ }
+ allSetBitmap |= element.getValue();
+ if ((bitmap & element.getValue()) != 0) {
+ s.add(element);
+ }
+ }
+ if (((~allSetBitmap) & bitmap) != 0) {
+ // check if only valid flags are set in the given bitmap
+ String msg = String.format("The bitmap %x for enum %s has " +
+ "bits set that are presented by any enum constant",
+ bitmap, type.getName());
+ throw new IllegalArgumentException(msg);
+ }
+ return s;
+ }
+
+ /**
+ * Return the bitmap mask with all possible bits set. E.g., If a bitmap
+ * has the individual flags 0x1, 0x2, and 0x8 (note the missing 0x4) then
+ * the mask will be 0xb (1011 binary)
+ *
+ * @param type The Enum class to use. Must implement BitmapableEnum
+ * @throws NullPointerException if type is null
+ * @throws IllegalArgumentException if any enum constant from type has
+ * more than one bit set
+ * @return an integer with all possible bits for the given bitmap enum
+ * type set.
+ */
+ public static <E extends Enum<E> & BitmapableEnum>
+ int getMask(Class<E> type) {
+ if (type == null) {
+ throw new NullPointerException("Given enum type must not be null");
+ }
+ // allSetBitmap will eventually have all valid bits for the given
+ // type set.
+ int allSetBitmap = 0;
+ for (E element: type.getEnumConstants()) {
+ if (Integer.bitCount(element.getValue()) != 1) {
+ String msg = String.format("The %s (%x) constant of the " +
+ "enum %s is supposed to represent a bitmap entry but " +
+ "has more than one bit set.",
+ element.toString(), element.getValue(), type.getName());
+ throw new IllegalArgumentException(msg);
+ }
+ allSetBitmap |= element.getValue();
+ }
+ return allSetBitmap;
+ }
+
+ /**
+ * Convert the given EnumSet to the integer bitmap representation.
+ * @param set The EnumSet to convert. The enum must implement
+ * BitmapableEnum
+ * @return the integer bitmap
+ * @throws IllegalArgumentException if an enum constant from the set (!) has
+ * more than one bit set
+ * @throws NullPointerException if the set is null
+ */
+ public static <E extends Enum<E> & BitmapableEnum>
+ int toBitmap(Set<E> set) {
+ if (set == null) {
+ throw new NullPointerException("Given set must not be null");
+ }
+ int bitmap = 0;
+ for (E element: set) {
+ if (Integer.bitCount(element.getValue()) != 1) {
+ String msg = String.format("The %s (%x) constant in the set " +
+ "is supposed to represent a bitmap entry but " +
+ "has more than one bit set.",
+ element.toString(), element.getValue());
+ throw new IllegalArgumentException(msg);
+ }
+ bitmap |= element.getValue();
+ }
+ return bitmap;
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/FilterIterator.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/FilterIterator.java
new file mode 100644
index 0000000..fdde82c
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/FilterIterator.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright 2012, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator that will filter values from an iterator and return only
+ * those values that match the predicate.
+ */
+public abstract class FilterIterator<T> implements Iterator<T> {
+ protected Iterator<T> subIterator;
+ protected T next;
+
+ /**
+ * Construct a filter iterator from the given sub iterator.
+ *
+ * @param subIterator the sub iterator over which we'll filter
+ */
+ public FilterIterator(Iterator<T> subIterator) {
+ super();
+ this.subIterator = subIterator;
+ }
+
+ /**
+ * Check whether the given value should be returned by the
+ * filter.
+ *
+ * @param value the value to check
+ * @return true if the value should be included
+ */
+ protected abstract boolean matches(T value);
+
+ // ***********
+ // Iterator<T>
+ // ***********
+
+ @Override
+ public boolean hasNext() {
+ if (next != null) {
+ return true;
+ }
+
+ while (subIterator.hasNext()) {
+ next = subIterator.next();
+ if (matches(next)) {
+ return true;
+ }
+ }
+ next = null;
+ return false;
+ }
+
+ @Override
+ public T next() {
+ if (hasNext()) {
+ T cur = next;
+ next = null;
+ return cur;
+ }
+ throw new NoSuchElementException();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/InstanceId.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/InstanceId.java
new file mode 100644
index 0000000..861dec6
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/InstanceId.java
@@ -0,0 +1,47 @@
+package net.onrc.onos.of.ctl.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * The class representing an ONOS Instance ID.
+ *
+ * This class is immutable.
+ */
+public final class InstanceId {
+ private final String id;
+
+ /**
+ * Constructor from a string value.
+ *
+ * @param id the value to use.
+ */
+ public InstanceId(String id) {
+ this.id = checkNotNull(id);
+ checkArgument(!id.isEmpty(), "Empty ONOS Instance ID");
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (!(obj instanceof InstanceId)) {
+ return false;
+ }
+
+ InstanceId that = (InstanceId) obj;
+ return this.id.equals(that.id);
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/IterableIterator.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/IterableIterator.java
new file mode 100644
index 0000000..79f3c9d
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/IterableIterator.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright 2012 Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Iterator over all values in an iterator of iterators.
+ *
+ * @param <T> the type of elements returned by this iterator
+ */
+public class IterableIterator<T> implements Iterator<T> {
+ Iterator<? extends Iterable<T>> subIterator;
+ Iterator<T> current = null;
+
+ public IterableIterator(Iterator<? extends Iterable<T>> subIterator) {
+ super();
+ this.subIterator = subIterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (current == null) {
+ if (subIterator.hasNext()) {
+ current = subIterator.next().iterator();
+ } else {
+ return false;
+ }
+ }
+ while (!current.hasNext() && subIterator.hasNext()) {
+ current = subIterator.next().iterator();
+ }
+
+ return current.hasNext();
+ }
+
+ @Override
+ public T next() {
+ if (hasNext()) {
+ return current.next();
+ }
+ throw new NoSuchElementException();
+ }
+
+ @Override
+ public void remove() {
+ if (hasNext()) {
+ current.remove();
+ }
+ throw new NoSuchElementException();
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/LRUHashMap.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/LRUHashMap.java
new file mode 100644
index 0000000..17f9354
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/LRUHashMap.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2011, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class LRUHashMap<K, V> extends LinkedHashMap<K, V> {
+
+ private static final long serialVersionUID = 1L;
+
+ private final int capacity;
+
+ public LRUHashMap(int capacity) {
+ super(capacity + 1, 0.75f, true);
+ this.capacity = capacity;
+ }
+
+ protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
+ return size() > capacity;
+ }
+
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/LinkedHashSetWrapper.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/LinkedHashSetWrapper.java
new file mode 100644
index 0000000..629e536
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/LinkedHashSetWrapper.java
@@ -0,0 +1,32 @@
+package net.onrc.onos.of.ctl.util;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+
+import com.google.common.collect.ForwardingCollection;
+
+/**
+ * A simple wrapper / forwarder that forwards all calls to a LinkedHashSet.
+ * This wrappers sole reason for existence is to implement the
+ * OrderedCollection marker interface.
+ *
+ */
+public class LinkedHashSetWrapper<E>
+ extends ForwardingCollection<E> implements OrderedCollection<E> {
+ private final Collection<E> delegate;
+
+ public LinkedHashSetWrapper() {
+ super();
+ this.delegate = new LinkedHashSet<E>();
+ }
+
+ public LinkedHashSetWrapper(Collection<? extends E> c) {
+ super();
+ this.delegate = new LinkedHashSet<E>(c);
+ }
+
+ @Override
+ protected Collection<E> delegate() {
+ return this.delegate;
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/MultiIterator.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/MultiIterator.java
new file mode 100644
index 0000000..693a8bf
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/MultiIterator.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright 2012 Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.util;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Iterator over all values in an iterator of iterators.
+ *
+ * @param <T> the type of elements returned by this iterator
+ */
+public class MultiIterator<T> implements Iterator<T> {
+ Iterator<Iterator<T>> subIterator;
+ Iterator<T> current = null;
+
+ public MultiIterator(Iterator<Iterator<T>> subIterator) {
+ super();
+ this.subIterator = subIterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (current == null) {
+ if (subIterator.hasNext()) {
+ current = subIterator.next();
+ } else {
+ return false;
+ }
+ }
+ while (!current.hasNext() && subIterator.hasNext()) {
+ current = subIterator.next();
+ }
+
+ return current.hasNext();
+ }
+
+ @Override
+ public T next() {
+ if (hasNext()) {
+ return current.next();
+ }
+ throw new NoSuchElementException();
+ }
+
+ @Override
+ public void remove() {
+ if (hasNext()) {
+ current.remove();
+ }
+ throw new NoSuchElementException();
+ }
+}
diff --git a/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/OrderedCollection.java b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/OrderedCollection.java
new file mode 100644
index 0000000..f032212
--- /dev/null
+++ b/of-save/ctl/src/main/java/net/onrc/onos/of/ctl/util/OrderedCollection.java
@@ -0,0 +1,14 @@
+package net.onrc.onos.of.ctl.util;
+
+import java.util.Collection;
+
+/**
+ * A marker interface indicating that this Collection defines a particular
+ * iteration order. The details about the iteration order are specified by
+ * the concrete implementation.
+ *
+ * @param <E>
+ */
+public interface OrderedCollection<E> extends Collection<E> {
+
+}
diff --git a/of-save/ctl/src/test/java/net/onrc/onos/of/ctl/internal/ControllerTest.java b/of-save/ctl/src/test/java/net/onrc/onos/of/ctl/internal/ControllerTest.java
new file mode 100644
index 0000000..ea7d884
--- /dev/null
+++ b/of-save/ctl/src/test/java/net/onrc/onos/of/ctl/internal/ControllerTest.java
@@ -0,0 +1,167 @@
+/**
+ * Copyright 2011, Big Switch Networks, Inc.
+ * Originally created by David Erickson, Stanford University
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License. You may obtain
+ * a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ **/
+
+package net.onrc.onos.of.ctl.internal;
+
+import junit.framework.TestCase;
+import net.onrc.onos.of.ctl.IOFSwitch;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+
+public class ControllerTest extends TestCase {
+
+ private Controller controller;
+ private IOFSwitch sw;
+ private OFChannelHandler h;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ sw = EasyMock.createMock(IOFSwitch.class);
+ h = EasyMock.createMock(OFChannelHandler.class);
+ controller = new Controller();
+ ControllerRunThread t = new ControllerRunThread();
+ t.start();
+ /*
+ * Making sure the thread is properly started before making calls
+ * to controller class.
+ */
+ Thread.sleep(200);
+ }
+
+ /**
+ * Starts the base mocks used in these tests.
+ */
+ private void startMocks() {
+ EasyMock.replay(sw, h);
+ }
+
+ /**
+ * Reset the mocks to a known state.
+ * Automatically called after tests.
+ */
+ @After
+ private void resetMocks() {
+ EasyMock.reset(sw);
+ }
+
+ /**
+ * Fetches the controller instance.
+ * @return the controller
+ */
+ public Controller getController() {
+ return controller;
+ }
+
+ /**
+ * Run the controller's main loop so that updates are processed.
+ */
+ protected class ControllerRunThread extends Thread {
+ @Override
+ public void run() {
+ controller.openFlowPort = 0; // Don't listen
+ controller.activate();
+ }
+ }
+
+ /**
+ * Verify that we are able to add a switch that just connected.
+ * If it already exists then this should fail
+ *
+ * @throws Exception error
+ */
+ @Test
+ public void testAddConnectedSwitches() throws Exception {
+ startMocks();
+ assertTrue(controller.addConnectedSwitch(0, h));
+ assertFalse(controller.addConnectedSwitch(0, h));
+ }
+
+ /**
+ * Add active master but cannot re-add active master.
+ * @throws Exception an error occurred.
+ */
+ @Test
+ public void testAddActivatedMasterSwitch() throws Exception {
+ startMocks();
+ controller.addConnectedSwitch(0, h);
+ assertTrue(controller.addActivatedMasterSwitch(0, sw));
+ assertFalse(controller.addActivatedMasterSwitch(0, sw));
+ }
+
+ /**
+ * Tests that an activated switch can be added but cannot be re-added.
+ *
+ * @throws Exception an error occurred
+ */
+ @Test
+ public void testAddActivatedEqualSwitch() throws Exception {
+ startMocks();
+ controller.addConnectedSwitch(0, h);
+ assertTrue(controller.addActivatedEqualSwitch(0, sw));
+ assertFalse(controller.addActivatedEqualSwitch(0, sw));
+ }
+
+ /**
+ * Move an equal switch to master.
+ * @throws Exception an error occurred
+ */
+ @Test
+ public void testTranstitionToMaster() throws Exception {
+ startMocks();
+ controller.addConnectedSwitch(0, h);
+ controller.addActivatedEqualSwitch(0, sw);
+ controller.transitionToMasterSwitch(0);
+ assertNotNull(controller.getMasterSwitch(0));
+ }
+
+ /**
+ * Transition a master switch to equal state.
+ * @throws Exception an error occurred
+ */
+ @Test
+ public void testTranstitionToEqual() throws Exception {
+ startMocks();
+ controller.addConnectedSwitch(0, h);
+ controller.addActivatedMasterSwitch(0, sw);
+ controller.transitionToEqualSwitch(0);
+ assertNotNull(controller.getEqualSwitch(0));
+ }
+
+ /**
+ * Remove the switch from the controller instance.
+ * @throws Exception an error occurred
+ */
+ @Test
+ public void testRemoveSwitch() throws Exception {
+ sw.cancelAllStatisticsReplies();
+ EasyMock.expectLastCall().once();
+ sw.setConnected(false);
+ EasyMock.expectLastCall().once();
+ startMocks();
+ controller.addConnectedSwitch(0, h);
+ controller.addActivatedMasterSwitch(0, sw);
+ controller.removeConnectedSwitch(0);
+ assertNull(controller.getSwitch(0));
+ EasyMock.verify(sw, h);
+ }
+}
diff --git a/of-save/ctl/src/test/java/net/onrc/onos/of/ctl/internal/OFChannelHandlerTest.java b/of-save/ctl/src/test/java/net/onrc/onos/of/ctl/internal/OFChannelHandlerTest.java
new file mode 100644
index 0000000..0213cce
--- /dev/null
+++ b/of-save/ctl/src/test/java/net/onrc/onos/of/ctl/internal/OFChannelHandlerTest.java
@@ -0,0 +1,1569 @@
+package net.onrc.onos.of.ctl.internal;
+
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import net.onrc.onos.of.ctl.IOFSwitch;
+import net.onrc.onos.of.ctl.Role;
+import net.onrc.onos.of.ctl.debugcounter.DebugCounter;
+import net.onrc.onos.of.ctl.debugcounter.IDebugCounterService;
+import net.onrc.onos.of.ctl.internal.OFChannelHandler.RoleRecvStatus;
+
+import org.easymock.Capture;
+import org.easymock.CaptureType;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipeline;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFExperimenter;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
+import org.projectfloodlight.openflow.protocol.OFHelloElem;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFNiciraControllerRole;
+import org.projectfloodlight.openflow.protocol.OFPacketIn;
+import org.projectfloodlight.openflow.protocol.OFPacketInReason;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFSetConfig;
+import org.projectfloodlight.openflow.protocol.OFStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsRequest;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.types.DatapathId;
+import org.projectfloodlight.openflow.types.U32;
+
+/**
+ * Channel handler deals with the switch connection and dispatches
+ * switch messages to the appropriate locations. These Unit Testing cases
+ * test the channeler state machine and role changer. In the first release,
+ * we will focus on OF version 1.0. we will add the testing case for
+ * version 1.3 later.
+ */
+public class OFChannelHandlerTest {
+ private Controller controller;
+ private IDebugCounterService debugCounterService;
+ private OFChannelHandler handler;
+ private Channel channel;
+ private ChannelHandlerContext ctx;
+ private MessageEvent messageEvent;
+ private ChannelStateEvent channelStateEvent;
+ private ChannelPipeline pipeline;
+ private Capture<ExceptionEvent> exceptionEventCapture;
+ private Capture<List<OFMessage>> writeCapture;
+ private OFFeaturesReply featuresReply;
+ private Set<Integer> seenXids = null;
+ private IOFSwitch swImplBase;
+ private OFVersion ofVersion = OFVersion.OF_10;
+ private OFFactory factory13;
+ private OFFactory factory10;
+ private OFFactory factory;
+
+ @Before
+ public void setUp() throws Exception {
+ controller = createMock(Controller.class);
+ ctx = createMock(ChannelHandlerContext.class);
+ channelStateEvent = createMock(ChannelStateEvent.class);
+ channel = createMock(Channel.class);
+ messageEvent = createMock(MessageEvent.class);
+ exceptionEventCapture = new Capture<ExceptionEvent>(CaptureType.ALL);
+ pipeline = createMock(ChannelPipeline.class);
+ writeCapture = new Capture<List<OFMessage>>(CaptureType.ALL);
+ swImplBase = createMock(IOFSwitch.class);
+ seenXids = null;
+ factory13 = OFFactories.getFactory(OFVersion.OF_13);
+ factory10 = OFFactories.getFactory(OFVersion.OF_10);
+ factory = (ofVersion == OFVersion.OF_13) ? factory13 : factory10;
+
+ // TODO: should mock IDebugCounterService and make sure
+ // the expected counters are updated.
+ debugCounterService = new DebugCounter();
+ Controller.Counters counters =
+ new Controller.Counters();
+ counters.createCounters(debugCounterService);
+ expect(controller.getCounters()).andReturn(counters).anyTimes();
+ expect(controller.getOFMessageFactory10()).andReturn(factory10)
+ .anyTimes();
+ expect(controller.getOFMessageFactory13()).andReturn(factory13)
+ .anyTimes();
+ expect(controller.addConnectedSwitch(2000, handler)).andReturn(true)
+ .anyTimes();
+ replay(controller);
+ handler = new OFChannelHandler(controller);
+ verify(controller);
+ reset(controller);
+
+ resetChannel();
+
+ // replay controller. Reset it if you need more specific behavior
+ replay(controller);
+
+ // replay switch. Reset it if you need more specific behavior
+ replay(swImplBase);
+
+ // Mock ctx and channelStateEvent
+ expect(ctx.getChannel()).andReturn(channel).anyTimes();
+ expect(channelStateEvent.getChannel()).andReturn(channel).anyTimes();
+ replay(ctx, channelStateEvent);
+
+ /* Setup an exception event capture on the channel. Right now
+ * we only expect exception events to be send up the channel.
+ * However, it's easy to extend to other events if we need it
+ */
+ pipeline.sendUpstream(capture(exceptionEventCapture));
+ expectLastCall().anyTimes();
+ replay(pipeline);
+ featuresReply = (OFFeaturesReply) buildOFMessage(OFType.FEATURES_REPLY);
+ }
+
+ @After
+ public void tearDown() {
+ /* ensure no exception was thrown */
+ if (exceptionEventCapture.hasCaptured()) {
+ Throwable ex = exceptionEventCapture.getValue().getCause();
+ throw new AssertionError("Unexpected exception: " +
+ ex.getClass().getName() + "(" + ex + ")");
+ }
+ assertFalse("Unexpected messages have been captured",
+ writeCapture.hasCaptured());
+ // verify all mocks.
+ verify(channel);
+ verify(messageEvent);
+ verify(controller);
+ verify(ctx);
+ verify(channelStateEvent);
+ verify(pipeline);
+ verify(swImplBase);
+
+ }
+
+ /**
+ * Reset the channel mock and set basic method call expectations.
+ *
+ **/
+ void resetChannel() {
+ reset(channel);
+ expect(channel.getPipeline()).andReturn(pipeline).anyTimes();
+ expect(channel.getRemoteAddress()).andReturn(null).anyTimes();
+ }
+
+ /**
+ * reset, setup, and replay the messageEvent mock for the given
+ * messages.
+ */
+ void setupMessageEvent(List<OFMessage> messages) {
+ reset(messageEvent);
+ expect(messageEvent.getMessage()).andReturn(messages).atLeastOnce();
+ replay(messageEvent);
+ }
+
+ /**
+ * reset, setup, and replay the messageEvent mock for the given
+ * messages, mock controller send message to channel handler.
+ *
+ * This method will reset, start replay on controller, and then verify
+ */
+ void sendMessageToHandlerWithControllerReset(List<OFMessage> messages)
+ throws Exception {
+ verify(controller);
+ reset(controller);
+
+ sendMessageToHandlerNoControllerReset(messages);
+ }
+
+ /**
+ * reset, setup, and replay the messageEvent mock for the given
+ * messages, mock controller send message to channel handler.
+ *
+ * This method will start replay on controller, and then verify
+ */
+ void sendMessageToHandlerNoControllerReset(List<OFMessage> messages)
+ throws Exception {
+ setupMessageEvent(messages);
+
+ expect(controller.addConnectedSwitch(1000, handler))
+ .andReturn(true).anyTimes();
+ replay(controller);
+
+ handler.messageReceived(ctx, messageEvent);
+ verify(controller);
+ }
+
+ /**
+ * Extract the list of OFMessages that was captured by the Channel.write()
+ * capture. Will check that something was actually captured first. We'll
+ * collapse the messages from multiple writes into a single list of
+ * OFMessages.
+ * Resets the channelWriteCapture.
+ */
+ List<OFMessage> getMessagesFromCapture() {
+ List<OFMessage> msgs = new ArrayList<OFMessage>();
+
+ assertTrue("No write on channel was captured",
+ writeCapture.hasCaptured());
+ List<List<OFMessage>> capturedVals = writeCapture.getValues();
+
+ for (List<OFMessage> oneWriteList: capturedVals) {
+ msgs.addAll(oneWriteList);
+ }
+ writeCapture.reset();
+ return msgs;
+ }
+
+
+ /**
+ * Verify that the given exception event capture (as returned by
+ * getAndInitExceptionCapture) has thrown an exception of the given
+ * expectedExceptionClass.
+ * Resets the capture
+ */
+ void verifyExceptionCaptured(
+ Class<? extends Throwable> expectedExceptionClass) {
+ assertTrue("Excpected exception not thrown",
+ exceptionEventCapture.hasCaptured());
+ Throwable caughtEx = exceptionEventCapture.getValue().getCause();
+ assertEquals(expectedExceptionClass, caughtEx.getClass());
+ exceptionEventCapture.reset();
+ }
+
+ /**
+ * Make sure that the transaction ids in the given messages are
+ * not 0 and differ between each other.
+ * While it's not a defect per se if the xids are we want to ensure
+ * we use different ones for each message we send.
+ */
+ void verifyUniqueXids(List<OFMessage> msgs) {
+ if (seenXids == null) {
+ seenXids = new HashSet<Integer>();
+ }
+ for (OFMessage m: msgs) {
+ int xid = (int) m.getXid();
+ assertTrue("Xid in messags is 0", xid != 0);
+ assertFalse("Xid " + xid + " has already been used",
+ seenXids.contains(xid));
+ seenXids.add(xid);
+ }
+ }
+
+
+
+ public void testInitState() throws Exception {
+ OFMessage m = buildOFMessage(OFType.HELLO);
+
+ expect(messageEvent.getMessage()).andReturn(null);
+ replay(channel, messageEvent);
+
+ // We don't expect to receive /any/ messages in init state since
+ // channelConnected moves us to a different state
+ sendMessageToHandlerWithControllerReset(Collections.singletonList(m));
+
+ verifyExceptionCaptured(SwitchStateException.class);
+ assertEquals(OFChannelHandler.ChannelState.INIT,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * move the channel from scratch to WAIT_HELLO state.
+ *
+ */
+ @Test
+ public void moveToWaitHello() throws Exception {
+ resetChannel();
+ channel.write(capture(writeCapture));
+ expectLastCall().andReturn(null).once();
+ replay(channel);
+ // replay unused mocks
+ replay(messageEvent);
+
+ handler.channelConnected(ctx, channelStateEvent);
+
+ List<OFMessage> msgs = getMessagesFromCapture();
+ assertEquals(1, msgs.size());
+ assertEquals(OFType.HELLO, msgs.get(0).getType());
+ assertEquals(OFChannelHandler.ChannelState.WAIT_HELLO,
+ handler.getStateForTesting());
+ //Should verify that the Hello received from the controller
+ //is ALWAYS OF1.3 hello regardless of the switch version
+ assertEquals(OFVersion.OF_13, msgs.get(0).getVersion());
+ verifyUniqueXids(msgs);
+ }
+
+
+ /**
+ * Move the channel from scratch to WAIT_FEATURES_REPLY state.
+ * Builds on moveToWaitHello().
+ * adds testing for WAIT_HELLO state.
+ */
+ @Test
+ public void moveToWaitFeaturesReply() throws Exception {
+ moveToWaitHello();
+ resetChannel();
+ channel.write(capture(writeCapture));
+ expectLastCall().andReturn(null).atLeastOnce();
+ replay(channel);
+
+ OFMessage hello = buildOFMessage(OFType.HELLO);
+ sendMessageToHandlerWithControllerReset(Collections.singletonList(hello));
+
+ List<OFMessage> msgs = getMessagesFromCapture();
+ assertEquals(1, msgs.size());
+ assertEquals(OFType.FEATURES_REQUEST, msgs.get(0).getType());
+ if (ofVersion == OFVersion.OF_10) {
+ assertEquals(OFVersion.OF_10, msgs.get(0).getVersion());
+ }
+ verifyUniqueXids(msgs);
+
+ assertEquals(OFChannelHandler.ChannelState.WAIT_FEATURES_REPLY,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel from scratch to WAIT_CONFIG_REPLY state.
+ * Builds on moveToWaitFeaturesReply.
+ * adds testing for WAIT_FEATURES_REPLY state.
+ */
+ @Test
+ public void moveToWaitConfigReply() throws Exception {
+ moveToWaitFeaturesReply();
+
+ resetChannel();
+ channel.write(capture(writeCapture));
+ expectLastCall().andReturn(null).atLeastOnce();
+ replay(channel);
+
+ sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(featuresReply));
+ List<OFMessage> msgs = getMessagesFromCapture();
+ assertEquals(3, msgs.size());
+ assertEquals(OFType.SET_CONFIG, msgs.get(0).getType());
+ OFSetConfig sc = (OFSetConfig) msgs.get(0);
+ assertEquals((short) 0xffff, sc.getMissSendLen());
+ assertEquals(OFType.BARRIER_REQUEST, msgs.get(1).getType());
+ assertEquals(OFType.GET_CONFIG_REQUEST, msgs.get(2).getType());
+ verifyUniqueXids(msgs);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_CONFIG_REPLY,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel from scratch to WAIT_DESCRIPTION_STAT_REPLY state.
+ * Builds on moveToWaitConfigReply().
+ * adds testing for WAIT_CONFIG_REPLY state.
+ */
+ @Test
+ public void moveToWaitDescriptionStatReply() throws Exception {
+ moveToWaitConfigReply();
+ resetChannel();
+ channel.write(capture(writeCapture));
+ expectLastCall().andReturn(null).atLeastOnce();
+ replay(channel);
+
+ OFGetConfigReply cr = (OFGetConfigReply) buildOFMessage(OFType.GET_CONFIG_REPLY);
+
+ sendMessageToHandlerWithControllerReset(Collections.<OFMessage>singletonList(cr));
+
+ List<OFMessage> msgs = getMessagesFromCapture();
+ assertEquals(1, msgs.size());
+ assertEquals(OFType.STATS_REQUEST, msgs.get(0).getType());
+ OFStatsRequest<?> sr = (OFStatsRequest<?>) msgs.get(0);
+ assertEquals(OFStatsType.DESC, sr.getStatsType());
+ verifyUniqueXids(msgs);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_DESCRIPTION_STAT_REPLY,
+ handler.getStateForTesting());
+ }
+
+
+ private OFStatsReply createDescriptionStatsReply() throws IOException {
+ OFStatsReply sr = (OFStatsReply) buildOFMessage(OFType.STATS_REPLY);
+ return sr;
+ }
+
+ /**
+ * Move the channel from scratch to WAIT_INITIAL_ROLE state.
+ * for a switch that does not have a sub-handshake.
+ * Builds on moveToWaitDescriptionStatReply().
+ * adds testing for WAIT_DESCRIPTION_STAT_REPLY state.
+ *
+ */
+ @Test
+ public void moveToWaitInitialRole()
+ throws Exception {
+ moveToWaitDescriptionStatReply();
+
+ long xid = 2000;
+
+ // build the stats reply
+ OFStatsReply sr = createDescriptionStatsReply();
+
+ resetChannel();
+ replay(channel);
+
+ setupMessageEvent(Collections.<OFMessage>singletonList(sr));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+ controller.submitRegistryRequest(1000);
+ expectLastCall().once();
+ replay(controller);
+
+ //TODO: With the description stats message you are sending in the test,
+ //you will end up with an OFSwitchImplBase object
+ //which by default does NOT support the nicira role messages.
+ //If you wish to test the case where Nicira role messages are supported,
+ //then make a comment here that states that this is different
+ //from the default behavior of switchImplbase /or/
+ //send the right desc-stats (for example send what is expected from OVS 1.0)
+
+ if (ofVersion == OFVersion.OF_10) {
+ expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+ .andReturn(true).once();
+
+ swImplBase.write(capture(writeCapture));
+ expectLastCall().anyTimes();
+ }
+
+ swImplBase.setOFVersion(ofVersion);
+ expectLastCall().once();
+ swImplBase.setConnected(true);
+ expectLastCall().once();
+ swImplBase.setChannel(channel);
+ expectLastCall().once();
+ swImplBase.setDebugCounterService(controller.getDebugCounter());
+ expectLastCall().once();
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ swImplBase.setRole(Role.EQUAL);
+ expectLastCall().once();
+
+ expect(swImplBase.getNextTransactionId())
+ .andReturn((int) xid).anyTimes();
+ expect(swImplBase.getId())
+ .andReturn(1000L).once();
+
+ swImplBase.setFeaturesReply(featuresReply);
+ expectLastCall().once();
+ swImplBase.setPortDescReply((OFPortDescStatsReply) null);
+ replay(swImplBase);
+
+ // send the description stats reply
+ handler.messageReceived(ctx, messageEvent);
+
+ List<OFMessage> msgs = getMessagesFromCapture();
+ assertEquals(1, msgs.size());
+ assertEquals(OFType.EXPERIMENTER, msgs.get(0).getType());
+ verifyNiciraMessage((OFExperimenter) msgs.get(0));
+
+ verify(controller);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel from scratch to.
+ * WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+ * Builds on moveToWaitInitialRole().
+ */
+ @Test
+ public void moveToWaitSubHandshake()
+ throws Exception {
+ moveToWaitInitialRole();
+
+ int xid = 2000;
+ resetChannel();
+ replay(channel);
+
+ reset(swImplBase);
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ // build the stats reply
+ OFStatsReply sr = createDescriptionStatsReply();
+ OFMessage rr = getRoleReply(xid, Role.SLAVE);
+ setupMessageEvent(Collections.<OFMessage>singletonList(rr));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+
+ replay(controller);
+
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ swImplBase.setRole(Role.SLAVE);
+ expectLastCall().once();
+ expect(swImplBase.getNextTransactionId())
+ .andReturn(xid).anyTimes();
+ swImplBase.startDriverHandshake();
+ expectLastCall().once();
+
+ //when this flag is false, state machine will move to
+ //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state
+ expect(swImplBase.isDriverHandshakeComplete())
+ .andReturn(false).once();
+
+ replay(swImplBase);
+
+ // send the description stats reply
+ handler.messageReceived(ctx, messageEvent);
+
+ assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel from scratch to WAIT_INITIAL_ROLE state,
+ * then move the channel to EQUAL state based on the switch Role.
+ * This test basically test the switch with role support.
+ * Builds on moveToWaitInitialRole().
+ *
+ * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
+ * and PORT_STATUS), state machine will transit to MASTER or
+ * EQUAL state based on the switch role.
+ */
+ @Test
+ public void moveToSlaveWithHandshakeComplete()
+ throws Exception {
+
+ moveToWaitInitialRole();
+
+ int xid = 2000;
+ resetChannel();
+ replay(channel);
+
+ reset(swImplBase);
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(true, xid, Role.SLAVE);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ // build the stats reply
+ OFStatsReply sr = createDescriptionStatsReply();
+ OFMessage rr = getRoleReply(xid, Role.SLAVE);
+ setupMessageEvent(Collections.<OFMessage>singletonList(rr));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+
+ expect(controller.addActivatedEqualSwitch(1000, swImplBase))
+ .andReturn(true).once();
+ replay(controller);
+
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ //consult the role in sw to determine the next state.
+ //in this testing case, we are testing that channel handler
+ // will move to EQUAL state when switch role is in SLAVE.
+ expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
+ swImplBase.setRole(Role.SLAVE);
+ expectLastCall().once();
+
+ expect(swImplBase.getNextTransactionId())
+ .andReturn(xid).anyTimes();
+ expect(swImplBase.getId())
+ .andReturn(1000L).once();
+ swImplBase.startDriverHandshake();
+ expectLastCall().once();
+
+ //when this flag is true, don't need to move interim state
+ //WAIT_SWITCH_DRIVER_SUB_HANDSHAKE. channel handler will
+ //move to corresponding state after consulting the role in sw
+ //This is essentially the same test as the one above,
+ //except for this line
+ expect(swImplBase.isDriverHandshakeComplete())
+ .andReturn(true).once();
+
+ replay(swImplBase);
+
+ // send the description stats reply
+ handler.messageReceived(ctx, messageEvent);
+
+ assertEquals(OFChannelHandler.ChannelState.EQUAL,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel from scratch to WAIT_INITIAL_ROLE state,
+ * then to MASTERL state based on the switch Role.
+ * This test basically test the switch with role support.
+ * Builds on moveToWaitInitialRole().
+ *
+ * In WAIT_INITIAL_ROLE state, when any messages (except ECHO_REQUEST
+ * and PORT_STATUS), state machine will transit to MASTER or
+ * EQUAL state based on the switch role.
+ */
+ @Test
+ public void moveToMasterWithHandshakeComplete()
+ throws Exception {
+
+ moveToWaitInitialRole();
+
+ int xid = 2000;
+ resetChannel();
+ replay(channel);
+
+ reset(swImplBase);
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ // build the stats reply
+ OFStatsReply sr = createDescriptionStatsReply();
+ OFMessage rr = getRoleReply(xid, Role.MASTER);
+ setupMessageEvent(Collections.<OFMessage>singletonList(rr));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+
+ expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+ .andReturn(true).once();
+ replay(controller);
+
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
+ swImplBase.setRole(Role.MASTER);
+ expectLastCall().once();
+
+ expect(swImplBase.getNextTransactionId())
+ .andReturn(xid).anyTimes();
+ expect(swImplBase.getId())
+ .andReturn(1000L).once();
+ swImplBase.startDriverHandshake();
+ expectLastCall().once();
+ expect(swImplBase.isDriverHandshakeComplete())
+ .andReturn(true).once();
+
+ replay(swImplBase);
+
+
+ // send the description stats reply
+ handler.messageReceived(ctx, messageEvent);
+
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel from scratch to
+ * WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+ * Builds on moveToWaitSubHandshake().
+ */
+ @Test
+ public void moveToEqualViaWaitSubHandshake()
+ throws Exception {
+ moveToWaitSubHandshake();
+
+ long xid = 2000;
+ resetChannel();
+ replay(channel);
+
+ // build the stats reply
+ OFStatsReply sr = createDescriptionStatsReply();
+
+ setupMessageEvent(Collections.<OFMessage>singletonList(sr));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+
+ expect(controller.addActivatedEqualSwitch(1000, swImplBase))
+ .andReturn(true).once();
+ replay(controller);
+
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ expect(swImplBase.getRole()).andReturn(Role.SLAVE).once();
+ expect(swImplBase.getNextTransactionId())
+ .andReturn((int) xid).anyTimes();
+ expect(swImplBase.getId())
+ .andReturn(1000L).once();
+
+ swImplBase.processDriverHandshakeMessage(sr);
+ expectLastCall().once();
+ expect(swImplBase.isDriverHandshakeComplete())
+ .andReturn(true).once();
+
+ replay(swImplBase);
+
+ // send the description stats reply
+ handler.messageReceived(ctx, messageEvent);
+
+ assertEquals(OFChannelHandler.ChannelState.EQUAL,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel from scratch to
+ * WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+ * Builds on moveToWaitSubHandshake().
+ */
+ @Test
+ public void moveToMasterViaWaitSubHandshake()
+ throws Exception {
+ moveToWaitSubHandshake();
+
+ long xid = 2000;
+ resetChannel();
+ replay(channel);
+
+ // In this state, any messages except echo request, port status and
+ // error go to the switch sub driver handshake. Once the switch reports
+ // that its sub driver handshake is complete (#isDriverHandshakeComplete
+ // return true) then the channel handle consults the switch role and
+ // moves the state machine to the appropriate state (MASTER or EQUALS).
+ // In this test we expect the state machine to end up in MASTER state.
+ OFStatsReply sr = createDescriptionStatsReply();
+
+ setupMessageEvent(Collections.<OFMessage>singletonList(sr));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+ expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+ .andReturn(true).once();
+ replay(controller);
+
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
+ expect(swImplBase.getNextTransactionId())
+ .andReturn((int) xid).anyTimes();
+ expect(swImplBase.getId())
+ .andReturn(1000L).once();
+
+ swImplBase.processDriverHandshakeMessage(sr);
+ expectLastCall().once();
+ expect(swImplBase.isDriverHandshakeComplete())
+ .andReturn(true).once();
+
+ replay(swImplBase);
+
+ // send the description stats reply
+ handler.messageReceived(ctx, messageEvent);
+ verify(controller);
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Test the behavior in WAIT_SWITCH_DRIVER_SUB_HANDSHAKE state.
+ * ECHO_REQUEST message received case.
+ */
+ @Test
+ public void testWaitSwitchDriverSubhandshake() throws Exception {
+ moveToWaitSubHandshake();
+
+ long xid = 2000;
+ resetChannel();
+ channel.write(capture(writeCapture));
+ expectLastCall().andReturn(null).atLeastOnce();
+ replay(channel);
+
+ OFMessage er = buildOFMessage(OFType.ECHO_REQUEST);
+
+ setupMessageEvent(Collections.<OFMessage>singletonList(er));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFMessageFactory10()).andReturn(factory10);
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+
+ replay(controller);
+
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ expect(swImplBase.getNextTransactionId())
+ .andReturn((int) xid).anyTimes();
+
+ replay(swImplBase);
+
+ handler.messageReceived(ctx, messageEvent);
+
+ List<OFMessage> msgs = getMessagesFromCapture();
+ assertEquals(1, msgs.size());
+ assertEquals(OFType.ECHO_REPLY, msgs.get(0).getType());
+ verifyUniqueXids(msgs);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_SWITCH_DRIVER_SUB_HANDSHAKE,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Helper.
+ * Verify that the given OFMessage is a correct Nicira RoleRequest message.
+ */
+ private void verifyNiciraMessage(OFExperimenter ofMessage) {
+
+ int vendor = (int) ofMessage.getExperimenter();
+ assertEquals(vendor, 0x2320); // magic number representing nicira
+ }
+
+ /**
+ * Setup the mock switch and write capture for a role request, set the
+ * role and verify mocks.
+ * @param supportsNxRole whether the switch supports role request messages
+ * to setup the attribute. This must be null (don't yet know if roles
+ * supported: send to check) or true.
+ * @param xid The xid to use in the role request
+ * @param role The role to send
+ * @throws IOException
+ */
+ private void setupSwitchSendRoleRequestAndVerify(Boolean supportsNxRole,
+ int xid,
+ Role role) throws IOException {
+
+ RoleRecvStatus expectation = RoleRecvStatus.MATCHED_SET_ROLE;
+
+ expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+ .andReturn(supportsNxRole).atLeastOnce();
+
+ if (supportsNxRole != null && supportsNxRole) {
+ expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
+ swImplBase.write(capture(writeCapture));
+ expectLastCall().anyTimes();
+ }
+ replay(swImplBase);
+
+ handler.sendRoleRequest(role, expectation);
+
+ if (supportsNxRole != null && supportsNxRole) {
+ List<OFMessage> msgs = getMessagesFromCapture();
+ assertEquals(1, msgs.size());
+ verifyNiciraMessage((OFExperimenter) msgs.get(0));
+ }
+ }
+
+ /**
+ * Setup the mock switch for a role change request where the switch
+ * does not support roles.
+ *
+ * Needs to verify and reset the controller since we need to set
+ * an expectation
+ */
+ private void setupSwitchRoleChangeUnsupported(int xid,
+ Role role) {
+ boolean supportsNxRole = false;
+ RoleRecvStatus expectation = RoleRecvStatus.NO_REPLY;
+ reset(swImplBase);
+ expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+ .andReturn(supportsNxRole).atLeastOnce();
+ // TODO: hmmm. While it's not incorrect that we set the attribute
+ // again it looks odd. Maybe change
+ swImplBase.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole);
+ expectLastCall().anyTimes();
+
+ replay(swImplBase);
+
+ handler.sendRoleRequest(role, expectation);
+
+ verify(swImplBase);
+ }
+
+ /*
+ * Return a Nicira RoleReply message for the given role.
+ */
+ private OFMessage getRoleReply(long xid, Role role) {
+
+ OFNiciraControllerRole nr = null;
+
+ switch(role) {
+ case MASTER:
+ nr = OFNiciraControllerRole.ROLE_MASTER;
+ break;
+ case EQUAL:
+ nr = OFNiciraControllerRole.ROLE_SLAVE;
+ break;
+ case SLAVE:
+ nr = OFNiciraControllerRole.ROLE_SLAVE;
+ break;
+ default: //handled below
+ }
+ OFMessage m = factory10.buildNiciraControllerRoleReply()
+ .setRole(nr)
+ .setXid(xid)
+ .build();
+ return m;
+ }
+
+ /**
+ * Move the channel from scratch to MASTER state.
+ * Builds on moveToWaitInitialRole().
+ * adds testing for WAIT_INITAL_ROLE state.
+ *
+ * This method tests the case that the switch does NOT support roles.
+ * In ONOS if the switch-driver says that nicira-role messages are not
+ * supported, then ONOS does NOT send role-request messages
+ * (see handleUnsentRoleMessage())
+ */
+ @Test
+ public void testInitialMoveToMasterNoRole() throws Exception {
+ int xid = 43;
+ // first, move us to WAIT_INITIAL_ROLE_STATE
+
+ moveToWaitInitialRole();
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ OFStatsReply sr = createDescriptionStatsReply();
+
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+
+ expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+ .andReturn(true).once();
+ replay(controller);
+
+ reset(swImplBase);
+ swImplBase.setRole(Role.MASTER);
+ expectLastCall().once();
+ swImplBase.startDriverHandshake();
+ expectLastCall().once();
+ expect(swImplBase.isDriverHandshakeComplete())
+ .andReturn(true).once();
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ expect(swImplBase.getRole()).andReturn(Role.MASTER).once();
+
+ expect(swImplBase.getId())
+ .andReturn(1000L).once();
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(false, xid, Role.MASTER);
+
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel from scratch to WAIT_INITIAL_ROLE state.
+ * Builds on moveToWaitInitialRole().
+ * adds testing for WAIT_INITAL_ROLE state
+ *
+ * We let the initial role request time out. Role support should be
+ * disabled but the switch should be activated.
+ */
+ /* TBD
+ @Test
+ public void testInitialMoveToMasterTimeout() throws Exception {
+ int timeout = 50;
+ handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
+ int xid = 4343;
+
+ // first, move us to WAIT_INITIAL_ROLE_STATE
+
+ moveToWaitInitialRole();
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ // prepare mocks and inject the role reply message
+ reset(swImplBase);
+ // Set the role
+ swImplBase.setRole(Role.MASTER);
+ expectLastCall().once();
+ swImplBase.startDriverHandshake();
+ expectLastCall().once();
+ expect(swImplBase.isDriverHandshakeComplete())
+ .andReturn(false).once();
+ if (ofVersion == OFVersion.OF_10) {
+ expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+ .andReturn(true).once();
+
+ swImplBase.write(capture(writeCapture),
+ EasyMock.<FloodlightContext>anyObject());
+ expectLastCall().anyTimes();
+ }
+ expect(swImplBase.getNextTransactionId()).andReturn(xid).once();
+
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(null, xid, Role.MASTER);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ OFMessage m = buildOFMessage(OFType.ECHO_REPLY);
+
+ setupMessageEvent(Collections.<OFMessage>singletonList(m));
+
+ Thread.sleep(timeout+5);
+
+ verify(controller);
+ reset(controller);
+
+ expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+ .andReturn(true).once();
+ controller.flushAll();
+ expectLastCall().once();
+
+ replay(controller);
+
+ handler.messageReceived(ctx, messageEvent);
+
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+
+ }
+
+ */
+ /**
+ * Move the channel from scratch to SLAVE state.
+ * Builds on doMoveToWaitInitialRole().
+ * adds testing for WAIT_INITAL_ROLE state
+ *
+ * This method tests the case that the switch does NOT support roles.
+ * The channel handler still needs to send the initial request to find
+ * out that whether the switch supports roles.
+ *
+ */
+ @Test
+ public void testInitialMoveToSlaveNoRole() throws Exception {
+ int xid = 44;
+ // first, move us to WAIT_INITIAL_ROLE_STATE
+ moveToWaitInitialRole();
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ reset(swImplBase);
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(false, xid, Role.SLAVE);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ }
+
+ /**
+ * Move the channel from scratch to SLAVE state.
+ * Builds on doMoveToWaitInitialRole().
+ * adds testing for WAIT_INITAL_ROLE state
+ *
+ * We let the initial role request time out. The switch should be
+ * disconnected
+ */
+ /* TBD
+ @Test
+ public void testInitialMoveToSlaveTimeout() throws Exception {
+ int timeout = 50;
+ handler.useRoleChangerWithOtherTimeoutForTesting(timeout);
+ int xid = 4444;
+
+ // first, move us to WAIT_INITIAL_ROLE_STATE
+ moveToWaitInitialRole();
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(null, xid, Role.SLAVE);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ // prepare mocks and inject the role reply message
+ reset(sw);
+ sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false);
+ expectLastCall().once();
+ sw.setRole(Role.SLAVE);
+ expectLastCall().once();
+ sw.disconnectSwitch(); // Make sure we disconnect
+ expectLastCall().once();
+ replay(sw);
+
+ OFMessage m = buildOFMessage(OFType.ECHO_REPLY);
+
+ Thread.sleep(timeout+5);
+
+ sendMessageToHandlerWithControllerReset(Collections.singletonList(m));
+ }
+
+ */
+ /**
+ * Move channel from scratch to WAIT_INITIAL_STATE, then MASTER,
+ * then SLAVE for cases where the switch does not support roles.
+ * I.e., the final SLAVE transition should disconnect the switch.
+ */
+ @Test
+ public void testNoRoleInitialToMasterToSlave() throws Exception {
+ int xid = 46;
+ reset(swImplBase);
+ replay(swImplBase);
+
+ reset(controller);
+ replay(controller);
+
+ // First, lets move the state to MASTER without role support
+ testInitialMoveToMasterNoRole();
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+
+ // try to set master role again. should be a no-op
+ setupSwitchRoleChangeUnsupported(xid, Role.MASTER);
+
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+
+ setupSwitchRoleChangeUnsupported(xid, Role.SLAVE);
+ //switch does not support role message. there is no role set
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+
+ }
+
+ /**
+ * Move the channel to MASTER state.
+ * Expects that the channel is in MASTER or SLAVE state.
+ *
+ */
+ public void changeRoleToMasterWithRequest() throws Exception {
+ int xid = 4242;
+
+ assertTrue("This method can only be called when handler is in " +
+ "MASTER or SLAVE role", handler.isHandshakeComplete());
+
+ reset(swImplBase);
+ reset(controller);
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
+
+ // prepare mocks and inject the role reply message
+
+ reset(controller);
+ expect(controller.addActivatedMasterSwitch(1000, swImplBase))
+ .andReturn(true).once();
+ OFMessage reply = getRoleReply(xid, Role.MASTER);
+
+ // sendMessageToHandler will verify and rest controller mock
+
+ OFStatsReply sr = createDescriptionStatsReply();
+ setupMessageEvent(Collections.<OFMessage>singletonList(reply));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+ controller.transitionToMasterSwitch(1000);
+ expectLastCall().once();
+
+ replay(controller);
+
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ expect(swImplBase.getRole()).andReturn(Role.EQUAL).atLeastOnce();
+ expect(swImplBase.getNextTransactionId())
+ .andReturn(xid).anyTimes();
+ expect(swImplBase.getId())
+ .andReturn(1000L).once();
+
+ swImplBase.setRole(Role.MASTER);
+ expectLastCall().once();
+ replay(swImplBase);
+
+ // send the description stats reply
+ handler.messageReceived(ctx, messageEvent);
+
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+ }
+
+ /**
+ * Move the channel to SLAVE state.
+ * Expects that the channel is in MASTER or SLAVE state.
+ *
+ */
+ public void changeRoleToSlaveWithRequest() throws Exception {
+ int xid = 2323;
+
+ assertTrue("This method can only be called when handler is in " +
+ "MASTER or SLAVE role", handler.isHandshakeComplete());
+
+ // Set the role
+ reset(controller);
+ reset(swImplBase);
+
+ swImplBase.write(capture(writeCapture));
+ expectLastCall().anyTimes();
+
+ expect(swImplBase.getNextTransactionId())
+ .andReturn(xid).anyTimes();
+
+
+ if (ofVersion == OFVersion.OF_10) {
+ expect(swImplBase.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE))
+ .andReturn(true).once();
+
+ swImplBase.write(capture(writeCapture));
+ expectLastCall().anyTimes();
+ }
+ replay(swImplBase);
+
+ handler.sendRoleRequest(Role.SLAVE, RoleRecvStatus.MATCHED_SET_ROLE);
+
+ List<OFMessage> msgs = getMessagesFromCapture();
+ assertEquals(1, msgs.size());
+ verifyNiciraMessage((OFExperimenter) msgs.get(0));
+
+
+ OFMessage reply = getRoleReply(xid, Role.SLAVE);
+ OFStatsReply sr = createDescriptionStatsReply();
+ setupMessageEvent(Collections.<OFMessage>singletonList(reply));
+
+ // mock controller
+ reset(controller);
+ reset(swImplBase);
+
+ controller.transitionToEqualSwitch(1000);
+ expectLastCall().once();
+ expect(controller.getOFSwitchInstance((OFDescStatsReply) sr, ofVersion))
+ .andReturn(swImplBase).anyTimes();
+
+ expect(controller.getDebugCounter())
+ .andReturn(debugCounterService).anyTimes();
+
+ replay(controller);
+
+ expect(swImplBase.getStringId())
+ .andReturn(null).anyTimes();
+ expect(swImplBase.getRole()).andReturn(Role.MASTER).atLeastOnce();
+ expect(swImplBase.getNextTransactionId())
+ .andReturn(xid).anyTimes();
+
+ // prepare mocks and inject the role reply message
+ swImplBase.setRole(Role.SLAVE);
+ expectLastCall().once();
+ expect(swImplBase.getId())
+ .andReturn(1000L).once();
+ replay(swImplBase);
+
+ handler.messageReceived(ctx, messageEvent);
+
+ assertEquals(OFChannelHandler.ChannelState.EQUAL,
+ handler.getStateForTesting());
+ }
+
+ @Test
+ public void testMultiRoleChange1() throws Exception {
+ moveToMasterWithHandshakeComplete();
+ changeRoleToMasterWithRequest();
+ changeRoleToSlaveWithRequest();
+ changeRoleToSlaveWithRequest();
+ changeRoleToMasterWithRequest();
+ changeRoleToSlaveWithRequest();
+ }
+
+ @Test
+ public void testMultiRoleChange2() throws Exception {
+ moveToSlaveWithHandshakeComplete();
+ changeRoleToMasterWithRequest();
+ changeRoleToSlaveWithRequest();
+ changeRoleToSlaveWithRequest();
+ changeRoleToMasterWithRequest();
+ changeRoleToSlaveWithRequest();
+ }
+
+ /**
+ * Start from scratch and reply with an unexpected error to the role
+ * change request.
+ * Builds on doMoveToWaitInitialRole()
+ * adds testing for WAIT_INITAL_ROLE state
+ */
+ /* TBD
+ @Test
+ public void testInitialRoleChangeOtherError() throws Exception {
+ int xid = 4343;
+ // first, move us to WAIT_INITIAL_ROLE_STATE
+ moveToWaitInitialRole();
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+ reset(swImplBase);
+ // Set the role
+ setupSwitchSendRoleRequestAndVerify(true, xid, Role.MASTER);
+ assertEquals(OFChannelHandler.ChannelState.WAIT_INITIAL_ROLE,
+ handler.getStateForTesting());
+
+
+ // FIXME: shouldn't use ordinal(), but OFError is broken
+
+ OFMessage err = factory.errorMsgs().buildBadActionErrorMsg()
+ .setCode(OFBadActionCode.BAD_LEN)
+ .setXid(2000)
+ .build();
+ verify(swImplBase);
+ reset(swImplBase);
+ replay(swImplBase);
+ sendMessageToHandlerWithControllerReset(Collections.singletonList(err));
+
+ verifyExceptionCaptured(SwitchStateException.class);
+ }
+ */
+ /**
+ * Test dispatch of messages while in MASTER role.
+ */
+ @Test
+ public void testMessageDispatchMaster() throws Exception {
+
+ moveToMasterWithHandshakeComplete();
+
+ // Send packet in. expect dispatch
+ OFPacketIn pi = (OFPacketIn)
+ buildOFMessage(OFType.PACKET_IN);
+ setupMessageEvent(Collections.<OFMessage>singletonList(pi));
+
+ reset(swImplBase);
+ swImplBase.handleMessage(pi);
+ expectLastCall().once();
+ replay(swImplBase);
+ // send the description stats reply
+ handler.messageReceived(ctx, messageEvent);
+
+ assertEquals(OFChannelHandler.ChannelState.MASTER,
+ handler.getStateForTesting());
+
+ verify(controller);
+ // TODO: many more to go
+ }
+
+ /**
+ * Test port status message handling while MASTER.
+ *
+ */
+ /* Patrick: TBD
+ @Test
+ public void testPortStatusMessageMaster() throws Exception {
+ long dpid = featuresReply.getDatapathId().getLong();
+ testInitialMoveToMasterWithRole();
+ List<OFPortDesc> ports = new ArrayList<OFPortDesc>();
+ // A dummy port.
+ OFPortDesc p = factory.buildPortDesc()
+ .setName("Eth1")
+ .setPortNo(OFPort.ofInt(1))
+ .build();
+ ports.add(p);
+
+ p.setName("Port1");
+ p.setPortNumber((short)1);
+
+ OFPortStatus ps = (OFPortStatus)buildOFMessage(OFType.PORT_STATUS);
+ ps.setDesc(p);
+
+ // The events we expect sw.handlePortStatus to return
+ // We'll just use the same list for all valid OFPortReasons and add
+ // arbitrary events for arbitrary ports that are not necessarily
+ // related to the port status message. Our goal
+ // here is not to return the correct set of events but the make sure
+ // that a) sw.handlePortStatus is called
+ // b) the list of events sw.handlePortStatus returns is sent
+ // as IOFSwitchListener notifications.
+ OrderedCollection<PortChangeEvent> events =
+ new LinkedHashSetWrapper<PortChangeEvent>();
+ ImmutablePort p1 = ImmutablePort.create("eth1", (short)1);
+ ImmutablePort p2 = ImmutablePort.create("eth2", (short)2);
+ ImmutablePort p3 = ImmutablePort.create("eth3", (short)3);
+ ImmutablePort p4 = ImmutablePort.create("eth4", (short)4);
+ ImmutablePort p5 = ImmutablePort.create("eth5", (short)5);
+ events.add(new PortChangeEvent(p1, PortChangeType.ADD));
+ events.add(new PortChangeEvent(p2, PortChangeType.DELETE));
+ events.add(new PortChangeEvent(p3, PortChangeType.UP));
+ events.add(new PortChangeEvent(p4, PortChangeType.DOWN));
+ events.add(new PortChangeEvent(p5, PortChangeType.OTHER_UPDATE));
+
+
+ for (OFPortReason reason: OFPortReason.values()) {
+ ps.setReason(reason.getReasonCode());
+
+ reset(sw);
+ expect(sw.getId()).andReturn(dpid).anyTimes();
+
+ expect(sw.processOFPortStatus(ps)).andReturn(events).once();
+ replay(sw);
+
+ reset(controller);
+ controller.notifyPortChanged(sw, p1, PortChangeType.ADD);
+ controller.notifyPortChanged(sw, p2, PortChangeType.DELETE);
+ controller.notifyPortChanged(sw, p3, PortChangeType.UP);
+ controller.notifyPortChanged(sw, p4, PortChangeType.DOWN);
+ controller.notifyPortChanged(sw, p5, PortChangeType.OTHER_UPDATE);
+ sendMessageToHandlerNoControllerReset(
+ Collections.<OFMessage>singletonList(ps));
+ verify(sw);
+ verify(controller);
+ }
+ }
+
+ */
+ /**
+ * Build an OF message.
+ * @throws IOException
+ */
+ private OFMessage buildOFMessage(OFType t) throws IOException {
+ OFMessage m = null;
+ switch (t) {
+
+ case HELLO:
+ // The OF protocol requires us to start things off by sending the highest
+ // version of the protocol supported.
+
+ // bitmap represents OF1.0 (ofp_version=0x01) and OF1.3 (ofp_version=0x04)
+ // see Sec. 7.5.1 of the OF1.3.4 spec
+ if (ofVersion == OFVersion.OF_13) {
+ U32 bitmap = U32.ofRaw(0x00000012);
+ OFHelloElem hem = factory13.buildHelloElemVersionbitmap()
+ .setBitmaps(Collections.singletonList(bitmap))
+ .build();
+ m = factory13.buildHello()
+ .setXid(2000)
+ .setElements(Collections.singletonList(hem))
+ .build();
+ } else {
+ m = factory10.buildHello()
+ .setXid(2000)
+ .build();
+ }
+ break;
+ case FEATURES_REQUEST:
+ m = factory.buildFeaturesRequest()
+ .setXid(2000)
+ .build();
+ break;
+ case FEATURES_REPLY:
+
+ m = factory.buildFeaturesReply()
+ .setDatapathId(DatapathId.of(1000L))
+ .setXid(2000)
+ .build();
+ break;
+ case SET_CONFIG:
+ m = factory.buildSetConfig()
+ .setMissSendLen((short) 0xffff)
+ .setXid(2000)
+ .build();
+ break;
+ case BARRIER_REQUEST:
+ m = factory.buildBarrierRequest()
+ .setXid(2000)
+ .build();
+ break;
+ case GET_CONFIG_REQUEST:
+ m = factory.buildGetConfigRequest()
+ .setXid(2000)
+ .build();
+ break;
+ case GET_CONFIG_REPLY:
+ m = factory.buildGetConfigReply()
+ .setMissSendLen((short) 0xffff)
+ .setXid(2000)
+ .build();
+ break;
+ case STATS_REQUEST:
+ break;
+ case STATS_REPLY:
+ m = factory.buildDescStatsReply()
+ .setDpDesc("Datapath Description")
+ .setHwDesc("Hardware Secription")
+ .setMfrDesc("Manufacturer Desctiption")
+ .setSerialNum("Serial Number")
+ .setSwDesc("Software Desription")
+ .build();
+ break;
+ case ECHO_REQUEST:
+ m = factory.buildEchoRequest()
+ .setXid(2000)
+ .build();
+ break;
+ case FLOW_REMOVED:
+ break;
+
+ case PACKET_IN:
+ m = factory.buildPacketIn()
+ .setReason(OFPacketInReason.NO_MATCH)
+ .setTotalLen(1500)
+ .setXid(2000)
+ .build();
+ break;
+ case PORT_STATUS:
+ m = factory.buildPortStatus()
+ .setXid(2000)
+ .build();
+ break;
+
+ default:
+ m = factory.buildFeaturesRequest()
+ .setXid(2000)
+ .build();
+ break;
+ }
+
+ return (m);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFActionType.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFActionType.java
new file mode 100644
index 0000000..fe5320d
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFActionType.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template const.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+
+public enum OFActionType {
+ OUTPUT,
+ SET_VLAN_VID,
+ SET_VLAN_PCP,
+ STRIP_VLAN,
+ SET_DL_SRC,
+ SET_DL_DST,
+ SET_NW_SRC,
+ SET_NW_DST,
+ SET_NW_TOS,
+ SET_TP_SRC,
+ SET_TP_DST,
+ ENQUEUE,
+ EXPERIMENTER,
+ SET_NW_ECN,
+ COPY_TTL_OUT,
+ COPY_TTL_IN,
+ SET_MPLS_LABEL,
+ SET_MPLS_TC,
+ SET_MPLS_TTL,
+ DEC_MPLS_TTL,
+ PUSH_VLAN,
+ POP_VLAN,
+ PUSH_MPLS,
+ POP_MPLS,
+ SET_QUEUE,
+ GROUP,
+ SET_NW_TTL,
+ DEC_NW_TTL,
+ SET_FIELD,
+ PUSH_PBB,
+ POP_PBB;
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAggregateStatsReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAggregateStatsReply.java
new file mode 100644
index 0000000..ce8478d
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAggregateStatsReply.java
@@ -0,0 +1,58 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFAggregateStatsReply extends OFObject, OFStatsReply {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ U64 getPacketCount();
+ U64 getByteCount();
+ long getFlowCount();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFStatsReply.Builder {
+ OFAggregateStatsReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ Builder setFlags(Set<OFStatsReplyFlags> flags);
+ U64 getPacketCount();
+ Builder setPacketCount(U64 packetCount);
+ U64 getByteCount();
+ Builder setByteCount(U64 byteCount);
+ long getFlowCount();
+ Builder setFlowCount(long flowCount);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAggregateStatsRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAggregateStatsRequest.java
new file mode 100644
index 0000000..e2c6cc2
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAggregateStatsRequest.java
@@ -0,0 +1,67 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFAggregateStatsRequest extends OFObject, OFStatsRequest<OFAggregateStatsReply>, OFRequest<OFAggregateStatsReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ TableId getTableId();
+ OFPort getOutPort();
+ OFGroup getOutGroup() throws UnsupportedOperationException;
+ U64 getCookie() throws UnsupportedOperationException;
+ U64 getCookieMask() throws UnsupportedOperationException;
+ Match getMatch();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFStatsRequest.Builder<OFAggregateStatsReply> {
+ OFAggregateStatsRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ Builder setFlags(Set<OFStatsRequestFlags> flags);
+ TableId getTableId();
+ Builder setTableId(TableId tableId);
+ OFPort getOutPort();
+ Builder setOutPort(OFPort outPort);
+ OFGroup getOutGroup() throws UnsupportedOperationException;
+ Builder setOutGroup(OFGroup outGroup) throws UnsupportedOperationException;
+ U64 getCookie() throws UnsupportedOperationException;
+ Builder setCookie(U64 cookie) throws UnsupportedOperationException;
+ U64 getCookieMask() throws UnsupportedOperationException;
+ Builder setCookieMask(U64 cookieMask) throws UnsupportedOperationException;
+ Match getMatch();
+ Builder setMatch(Match match);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncGetReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncGetReply.java
new file mode 100644
index 0000000..d29b921
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncGetReply.java
@@ -0,0 +1,61 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFAsyncGetReply extends OFObject, OFMessage {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getPacketInMaskEqualMaster();
+ long getPacketInMaskSlave();
+ long getPortStatusMaskEqualMaster();
+ long getPortStatusMaskSlave();
+ long getFlowRemovedMaskEqualMaster();
+ long getFlowRemovedMaskSlave();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFMessage.Builder {
+ OFAsyncGetReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getPacketInMaskEqualMaster();
+ Builder setPacketInMaskEqualMaster(long packetInMaskEqualMaster);
+ long getPacketInMaskSlave();
+ Builder setPacketInMaskSlave(long packetInMaskSlave);
+ long getPortStatusMaskEqualMaster();
+ Builder setPortStatusMaskEqualMaster(long portStatusMaskEqualMaster);
+ long getPortStatusMaskSlave();
+ Builder setPortStatusMaskSlave(long portStatusMaskSlave);
+ long getFlowRemovedMaskEqualMaster();
+ Builder setFlowRemovedMaskEqualMaster(long flowRemovedMaskEqualMaster);
+ long getFlowRemovedMaskSlave();
+ Builder setFlowRemovedMaskSlave(long flowRemovedMaskSlave);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncGetRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncGetRequest.java
new file mode 100644
index 0000000..6f52220
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncGetRequest.java
@@ -0,0 +1,61 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFAsyncGetRequest extends OFObject, OFMessage, OFRequest<OFAsyncGetReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getPacketInMaskEqualMaster();
+ long getPacketInMaskSlave();
+ long getPortStatusMaskEqualMaster();
+ long getPortStatusMaskSlave();
+ long getFlowRemovedMaskEqualMaster();
+ long getFlowRemovedMaskSlave();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFMessage.Builder {
+ OFAsyncGetRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getPacketInMaskEqualMaster();
+ Builder setPacketInMaskEqualMaster(long packetInMaskEqualMaster);
+ long getPacketInMaskSlave();
+ Builder setPacketInMaskSlave(long packetInMaskSlave);
+ long getPortStatusMaskEqualMaster();
+ Builder setPortStatusMaskEqualMaster(long portStatusMaskEqualMaster);
+ long getPortStatusMaskSlave();
+ Builder setPortStatusMaskSlave(long portStatusMaskSlave);
+ long getFlowRemovedMaskEqualMaster();
+ Builder setFlowRemovedMaskEqualMaster(long flowRemovedMaskEqualMaster);
+ long getFlowRemovedMaskSlave();
+ Builder setFlowRemovedMaskSlave(long flowRemovedMaskSlave);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncSet.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncSet.java
new file mode 100644
index 0000000..ff3927e
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFAsyncSet.java
@@ -0,0 +1,62 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFAsyncSet extends OFObject, OFMessage {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getPacketInMaskEqualMaster();
+ long getPacketInMaskSlave();
+ long getPortStatusMaskEqualMaster();
+ long getPortStatusMaskSlave();
+ long getFlowRemovedMaskEqualMaster();
+ long getFlowRemovedMaskSlave();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFMessage.Builder {
+ OFAsyncSet build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getPacketInMaskEqualMaster();
+ Builder setPacketInMaskEqualMaster(long packetInMaskEqualMaster);
+ long getPacketInMaskSlave();
+ Builder setPacketInMaskSlave(long packetInMaskSlave);
+ long getPortStatusMaskEqualMaster();
+ Builder setPortStatusMaskEqualMaster(long portStatusMaskEqualMaster);
+ long getPortStatusMaskSlave();
+ Builder setPortStatusMaskSlave(long portStatusMaskSlave);
+ long getFlowRemovedMaskEqualMaster();
+ Builder setFlowRemovedMaskEqualMaster(long flowRemovedMaskEqualMaster);
+ long getFlowRemovedMaskSlave();
+ Builder setFlowRemovedMaskSlave(long flowRemovedMaskSlave);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadActionCode.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadActionCode.java
new file mode 100644
index 0000000..13d5543
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadActionCode.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template const.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+
+public enum OFBadActionCode {
+ BAD_TYPE,
+ BAD_LEN,
+ BAD_EXPERIMENTER,
+ BAD_EXPERIMENTER_TYPE,
+ BAD_OUT_PORT,
+ BAD_ARGUMENT,
+ EPERM,
+ TOO_MANY,
+ BAD_QUEUE,
+ BAD_OUT_GROUP,
+ MATCH_INCONSISTENT,
+ UNSUPPORTED_ORDER,
+ BAD_TAG,
+ BAD_SET_TYPE,
+ BAD_SET_LEN,
+ BAD_SET_ARGUMENT;
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadInstructionCode.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadInstructionCode.java
new file mode 100644
index 0000000..dfe86d3
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadInstructionCode.java
@@ -0,0 +1,38 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template const.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+
+public enum OFBadInstructionCode {
+ UNKNOWN_INST,
+ UNSUP_INST,
+ BAD_TABLE_ID,
+ UNSUP_METADATA,
+ UNSUP_METADATA_MASK,
+ UNSUP_EXP_INST,
+ BAD_EXPERIMENTER,
+ BAD_EXPERIMENTER_TYPE,
+ BAD_LEN,
+ EPERM;
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadMatchCode.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadMatchCode.java
new file mode 100644
index 0000000..02f689a
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadMatchCode.java
@@ -0,0 +1,40 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template const.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+
+public enum OFBadMatchCode {
+ BAD_TYPE,
+ BAD_LEN,
+ BAD_TAG,
+ BAD_DL_ADDR_MASK,
+ BAD_NW_ADDR_MASK,
+ BAD_WILDCARDS,
+ BAD_FIELD,
+ BAD_VALUE,
+ BAD_MASK,
+ BAD_PREREQ,
+ DUP_FIELD,
+ EPERM;
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadRequestCode.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadRequestCode.java
new file mode 100644
index 0000000..e254cb2
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBadRequestCode.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template const.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+
+public enum OFBadRequestCode {
+ BAD_VERSION,
+ BAD_TYPE,
+ BAD_STAT,
+ BAD_EXPERIMENTER,
+ BAD_SUBTYPE,
+ EPERM,
+ BAD_LEN,
+ BUFFER_EMPTY,
+ BUFFER_UNKNOWN,
+ BAD_TABLE_ID,
+ BAD_EXPERIMENTER_TYPE,
+ IS_SLAVE,
+ BAD_PORT,
+ BAD_PACKET,
+ MULTIPART_BUFFER_OVERFLOW;
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBarrierReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBarrierReply.java
new file mode 100644
index 0000000..f64f16e
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBarrierReply.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBarrierReply extends OFObject, OFMessage {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFMessage.Builder {
+ OFBarrierReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBarrierRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBarrierRequest.java
new file mode 100644
index 0000000..b41e104
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBarrierRequest.java
@@ -0,0 +1,43 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBarrierRequest extends OFObject, OFMessage, OFRequest<OFBarrierReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFMessage.Builder {
+ OFBarrierRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnArpIdle.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnArpIdle.java
new file mode 100644
index 0000000..3d1893e
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnArpIdle.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnArpIdle extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ int getVlanVid();
+ IPv4Address getIpv4Addr();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnArpIdle build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ int getVlanVid();
+ Builder setVlanVid(int vlanVid);
+ IPv4Address getIpv4Addr();
+ Builder setIpv4Addr(IPv4Address ipv4Addr);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwClearDataReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwClearDataReply.java
new file mode 100644
index 0000000..78e74c5
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwClearDataReply.java
@@ -0,0 +1,50 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnBwClearDataReply extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ long getStatus();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnBwClearDataReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ long getStatus();
+ Builder setStatus(long status);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwClearDataRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwClearDataRequest.java
new file mode 100644
index 0000000..bb9c2bb
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwClearDataRequest.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnBwClearDataRequest extends OFObject, OFBsnHeader, OFRequest<OFBsnBwClearDataReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnBwClearDataRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableGetReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableGetReply.java
new file mode 100644
index 0000000..e8ae108
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableGetReply.java
@@ -0,0 +1,50 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnBwEnableGetReply extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ long getEnabled();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnBwEnableGetReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ long getEnabled();
+ Builder setEnabled(long enabled);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableGetRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableGetRequest.java
new file mode 100644
index 0000000..15ccbdc
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableGetRequest.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnBwEnableGetRequest extends OFObject, OFBsnHeader, OFRequest<OFBsnBwEnableGetReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnBwEnableGetRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableSetReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableSetReply.java
new file mode 100644
index 0000000..6d25d7e
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableSetReply.java
@@ -0,0 +1,54 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnBwEnableSetReply extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ long getEnable();
+ long getStatus();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnBwEnableSetReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ long getEnable();
+ Builder setEnable(long enable);
+ long getStatus();
+ Builder setStatus(long status);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableSetRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableSetRequest.java
new file mode 100644
index 0000000..2b23800
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnBwEnableSetRequest.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnBwEnableSetRequest extends OFObject, OFBsnHeader, OFRequest<OFBsnBwEnableSetReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ long getEnable();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnBwEnableSetRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ long getEnable();
+ Builder setEnable(long enable);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnection.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnection.java
new file mode 100644
index 0000000..6d11288
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnection.java
@@ -0,0 +1,50 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnControllerConnection extends OFObject {
+ OFBsnControllerConnectionState getState();
+ OFAuxId getAuxiliaryId();
+ OFControllerRole getRole();
+ String getUri();
+ OFVersion getVersion();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder {
+ OFBsnControllerConnection build();
+ OFBsnControllerConnectionState getState();
+ Builder setState(OFBsnControllerConnectionState state);
+ OFAuxId getAuxiliaryId();
+ Builder setAuxiliaryId(OFAuxId auxiliaryId);
+ OFControllerRole getRole();
+ Builder setRole(OFControllerRole role);
+ String getUri();
+ Builder setUri(String uri);
+ OFVersion getVersion();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionState.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionState.java
new file mode 100644
index 0000000..df1312f
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionState.java
@@ -0,0 +1,30 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template const.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+
+public enum OFBsnControllerConnectionState {
+ BSN_CONTROLLER_CONNECTION_STATE_DISCONNECTED,
+ BSN_CONTROLLER_CONNECTION_STATE_CONNECTED;
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionsReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionsReply.java
new file mode 100644
index 0000000..ffa03c4
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionsReply.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.List;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnControllerConnectionsReply extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnControllerConnection> getConnections();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnControllerConnectionsReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnControllerConnection> getConnections();
+ Builder setConnections(List<OFBsnControllerConnection> connections);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionsRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionsRequest.java
new file mode 100644
index 0000000..efee303
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerConnectionsRequest.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnControllerConnectionsRequest extends OFObject, OFBsnHeader, OFRequest<OFBsnControllerConnectionsReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnControllerConnectionsRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerRoleReason.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerRoleReason.java
new file mode 100644
index 0000000..a8eb119
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnControllerRoleReason.java
@@ -0,0 +1,31 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template const.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+
+public enum OFBsnControllerRoleReason {
+ BSN_CONTROLLER_ROLE_REASON_MASTER_REQUEST,
+ BSN_CONTROLLER_ROLE_REASON_CONFIG,
+ BSN_CONTROLLER_ROLE_REASON_EXPERIMENTER;
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsEntry.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsEntry.java
new file mode 100644
index 0000000..0aa4407
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsEntry.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnDebugCounterDescStatsEntry extends OFObject {
+ U64 getCounterId();
+ String getName();
+ String getDescription();
+ OFVersion getVersion();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder {
+ OFBsnDebugCounterDescStatsEntry build();
+ U64 getCounterId();
+ Builder setCounterId(U64 counterId);
+ String getName();
+ Builder setName(String name);
+ String getDescription();
+ Builder setDescription(String description);
+ OFVersion getVersion();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsReply.java
new file mode 100644
index 0000000..5f72426
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsReply.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import java.util.List;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnDebugCounterDescStatsReply extends OFObject, OFBsnStatsReply {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnDebugCounterDescStatsEntry> getEntries();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsReply.Builder {
+ OFBsnDebugCounterDescStatsReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ Builder setFlags(Set<OFStatsReplyFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnDebugCounterDescStatsEntry> getEntries();
+ Builder setEntries(List<OFBsnDebugCounterDescStatsEntry> entries);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsRequest.java
new file mode 100644
index 0000000..ebd3b9b
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterDescStatsRequest.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnDebugCounterDescStatsRequest extends OFObject, OFBsnStatsRequest<OFBsnDebugCounterDescStatsReply>, OFRequest<OFBsnDebugCounterDescStatsReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsRequest.Builder<OFBsnDebugCounterDescStatsReply> {
+ OFBsnDebugCounterDescStatsRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ Builder setFlags(Set<OFStatsRequestFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsEntry.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsEntry.java
new file mode 100644
index 0000000..f3d28d0
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsEntry.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnDebugCounterStatsEntry extends OFObject {
+ U64 getCounterId();
+ U64 getValue();
+ OFVersion getVersion();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder {
+ OFBsnDebugCounterStatsEntry build();
+ U64 getCounterId();
+ Builder setCounterId(U64 counterId);
+ U64 getValue();
+ Builder setValue(U64 value);
+ OFVersion getVersion();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsReply.java
new file mode 100644
index 0000000..9edf42a
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsReply.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import java.util.List;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnDebugCounterStatsReply extends OFObject, OFBsnStatsReply {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnDebugCounterStatsEntry> getEntries();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsReply.Builder {
+ OFBsnDebugCounterStatsReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ Builder setFlags(Set<OFStatsReplyFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnDebugCounterStatsEntry> getEntries();
+ Builder setEntries(List<OFBsnDebugCounterStatsEntry> entries);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsRequest.java
new file mode 100644
index 0000000..cb2d5f9
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnDebugCounterStatsRequest.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnDebugCounterStatsRequest extends OFObject, OFBsnStatsRequest<OFBsnDebugCounterStatsReply>, OFRequest<OFBsnDebugCounterStatsReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsRequest.Builder<OFBsnDebugCounterStatsReply> {
+ OFBsnDebugCounterStatsRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ Builder setFlags(Set<OFStatsRequestFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsEntry.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsEntry.java
new file mode 100644
index 0000000..d709799
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsEntry.java
@@ -0,0 +1,41 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnFlowChecksumBucketStatsEntry extends OFObject {
+ U64 getChecksum();
+ OFVersion getVersion();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder {
+ OFBsnFlowChecksumBucketStatsEntry build();
+ U64 getChecksum();
+ Builder setChecksum(U64 checksum);
+ OFVersion getVersion();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsReply.java
new file mode 100644
index 0000000..4759d45
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsReply.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import java.util.List;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnFlowChecksumBucketStatsReply extends OFObject, OFBsnStatsReply {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnFlowChecksumBucketStatsEntry> getEntries();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsReply.Builder {
+ OFBsnFlowChecksumBucketStatsReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ Builder setFlags(Set<OFStatsReplyFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnFlowChecksumBucketStatsEntry> getEntries();
+ Builder setEntries(List<OFBsnFlowChecksumBucketStatsEntry> entries);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsRequest.java
new file mode 100644
index 0000000..1f4ed0d
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowChecksumBucketStatsRequest.java
@@ -0,0 +1,56 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnFlowChecksumBucketStatsRequest extends OFObject, OFBsnStatsRequest<OFBsnFlowChecksumBucketStatsReply>, OFRequest<OFBsnFlowChecksumBucketStatsReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+ TableId getTableId();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsRequest.Builder<OFBsnFlowChecksumBucketStatsReply> {
+ OFBsnFlowChecksumBucketStatsRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ Builder setFlags(Set<OFStatsRequestFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ TableId getTableId();
+ Builder setTableId(TableId tableId);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdle.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdle.java
new file mode 100644
index 0000000..88a2b14
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdle.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnFlowIdle extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ U64 getCookie();
+ int getPriority();
+ TableId getTableId();
+ Match getMatch();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnFlowIdle build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ U64 getCookie();
+ Builder setCookie(U64 cookie);
+ int getPriority();
+ Builder setPriority(int priority);
+ TableId getTableId();
+ Builder setTableId(TableId tableId);
+ Match getMatch();
+ Builder setMatch(Match match);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableGetReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableGetReply.java
new file mode 100644
index 0000000..cf38356
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableGetReply.java
@@ -0,0 +1,50 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnFlowIdleEnableGetReply extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ long getEnabled();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnFlowIdleEnableGetReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ long getEnabled();
+ Builder setEnabled(long enabled);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableGetRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableGetRequest.java
new file mode 100644
index 0000000..aacb08c
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableGetRequest.java
@@ -0,0 +1,47 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnFlowIdleEnableGetRequest extends OFObject, OFBsnHeader, OFRequest<OFBsnFlowIdleEnableGetReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnFlowIdleEnableGetRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableSetReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableSetReply.java
new file mode 100644
index 0000000..6c0b274
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableSetReply.java
@@ -0,0 +1,54 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnFlowIdleEnableSetReply extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ long getEnable();
+ long getStatus();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnFlowIdleEnableSetReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ long getEnable();
+ Builder setEnable(long enable);
+ long getStatus();
+ Builder setStatus(long status);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableSetRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableSetRequest.java
new file mode 100644
index 0000000..aae991d
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnFlowIdleEnableSetRequest.java
@@ -0,0 +1,51 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnFlowIdleEnableSetRequest extends OFObject, OFBsnHeader, OFRequest<OFBsnFlowIdleEnableSetReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ long getEnable();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnFlowIdleEnableSetRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ long getEnable();
+ Builder setEnable(long enable);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsEntry.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsEntry.java
new file mode 100644
index 0000000..d69a444
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsEntry.java
@@ -0,0 +1,41 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableBucketStatsEntry extends OFObject {
+ U128 getChecksum();
+ OFVersion getVersion();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder {
+ OFBsnGentableBucketStatsEntry build();
+ U128 getChecksum();
+ Builder setChecksum(U128 checksum);
+ OFVersion getVersion();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsReply.java
new file mode 100644
index 0000000..0b08078
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsReply.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import java.util.List;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableBucketStatsReply extends OFObject, OFBsnStatsReply {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnGentableBucketStatsEntry> getEntries();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsReply.Builder {
+ OFBsnGentableBucketStatsReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ Builder setFlags(Set<OFStatsReplyFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnGentableBucketStatsEntry> getEntries();
+ Builder setEntries(List<OFBsnGentableBucketStatsEntry> entries);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsRequest.java
new file mode 100644
index 0000000..72b5983
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableBucketStatsRequest.java
@@ -0,0 +1,56 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableBucketStatsRequest extends OFObject, OFBsnStatsRequest<OFBsnGentableBucketStatsReply>, OFRequest<OFBsnGentableBucketStatsReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+ GenTableId getTableId();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsRequest.Builder<OFBsnGentableBucketStatsReply> {
+ OFBsnGentableBucketStatsRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ Builder setFlags(Set<OFStatsRequestFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ GenTableId getTableId();
+ Builder setTableId(GenTableId tableId);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableClearReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableClearReply.java
new file mode 100644
index 0000000..d0c7015
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableClearReply.java
@@ -0,0 +1,56 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableClearReply extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ GenTableId getTableId();
+ long getDeletedCount();
+ long getErrorCount();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnGentableClearReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ GenTableId getTableId();
+ Builder setTableId(GenTableId tableId);
+ long getDeletedCount();
+ Builder setDeletedCount(long deletedCount);
+ long getErrorCount();
+ Builder setErrorCount(long errorCount);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableClearRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableClearRequest.java
new file mode 100644
index 0000000..e61f3f6
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableClearRequest.java
@@ -0,0 +1,56 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableClearRequest extends OFObject, OFBsnHeader, OFRequest<OFBsnGentableClearReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ GenTableId getTableId();
+ U128 getChecksum();
+ U128 getChecksumMask();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnGentableClearRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ GenTableId getTableId();
+ Builder setTableId(GenTableId tableId);
+ U128 getChecksum();
+ Builder setChecksum(U128 checksum);
+ U128 getChecksumMask();
+ Builder setChecksumMask(U128 checksumMask);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsEntry.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsEntry.java
new file mode 100644
index 0000000..b39fd10
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsEntry.java
@@ -0,0 +1,50 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableDescStatsEntry extends OFObject {
+ GenTableId getTableId();
+ String getName();
+ long getBucketsSize();
+ long getMaxEntries();
+ OFVersion getVersion();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder {
+ OFBsnGentableDescStatsEntry build();
+ GenTableId getTableId();
+ Builder setTableId(GenTableId tableId);
+ String getName();
+ Builder setName(String name);
+ long getBucketsSize();
+ Builder setBucketsSize(long bucketsSize);
+ long getMaxEntries();
+ Builder setMaxEntries(long maxEntries);
+ OFVersion getVersion();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsReply.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsReply.java
new file mode 100644
index 0000000..6d2de9d
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsReply.java
@@ -0,0 +1,57 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import java.util.List;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableDescStatsReply extends OFObject, OFBsnStatsReply {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnGentableDescStatsEntry> getEntries();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsReply.Builder {
+ OFBsnGentableDescStatsReply build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsReplyFlags> getFlags();
+ Builder setFlags(Set<OFStatsReplyFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ List<OFBsnGentableDescStatsEntry> getEntries();
+ Builder setEntries(List<OFBsnGentableDescStatsEntry> entries);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsRequest.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsRequest.java
new file mode 100644
index 0000000..8fa686d
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableDescStatsRequest.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableDescStatsRequest extends OFObject, OFBsnStatsRequest<OFBsnGentableDescStatsReply>, OFRequest<OFBsnGentableDescStatsReply> {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ long getExperimenter();
+ long getSubtype();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnStatsRequest.Builder<OFBsnGentableDescStatsReply> {
+ OFBsnGentableDescStatsRequest build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ OFStatsType getStatsType();
+ Set<OFStatsRequestFlags> getFlags();
+ Builder setFlags(Set<OFStatsRequestFlags> flags);
+ long getExperimenter();
+ long getSubtype();
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableEntryAdd.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableEntryAdd.java
new file mode 100644
index 0000000..ef358fa
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableEntryAdd.java
@@ -0,0 +1,60 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_interface.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import java.util.List;
+import org.jboss.netty.buffer.ChannelBuffer;
+
+public interface OFBsnGentableEntryAdd extends OFObject, OFBsnHeader {
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ long getExperimenter();
+ long getSubtype();
+ GenTableId getTableId();
+ U128 getChecksum();
+ List<OFBsnTlv> getKey();
+ List<OFBsnTlv> getValue();
+
+ void writeTo(ChannelBuffer channelBuffer);
+
+ Builder createBuilder();
+ public interface Builder extends OFBsnHeader.Builder {
+ OFBsnGentableEntryAdd build();
+ OFVersion getVersion();
+ OFType getType();
+ long getXid();
+ Builder setXid(long xid);
+ long getExperimenter();
+ long getSubtype();
+ GenTableId getTableId();
+ Builder setTableId(GenTableId tableId);
+ U128 getChecksum();
+ Builder setChecksum(U128 checksum);
+ List<OFBsnTlv> getKey();
+ Builder setKey(List<OFBsnTlv> key);
+ List<OFBsnTlv> getValue();
+ Builder setValue(List<OFBsnTlv> value);
+ }
+}
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableEntryDelete.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/OFBsnGentableEntryDelete.java
new file mode 100644
index 0000000..79093a3
--- /dev/null
+++ b/of-save/lib/gen-src/ma