Giant patch of changes to support OpenFlow 1.3

The following people have contributed to this patch:
- Ali Al-Shabibi <alshabibi.ali@gmail.com>
- Ayaka Koshibe <ayaka@onlab.us>
- Brian O'Connor <bocon@onlab.us>
- Jonathan Hart <jono@onlab.us>
- Matteo Gerola <mgerola@create-net.org>
- Michele Santuari <michele.santuari@create-net.org>
- Pavlin Radoslavov <pavlin@onlab.us>
- Saurav Das <sauravdas@alumni.stanford.edu>
- Toshio Koide <t-koide@onlab.us>
- Yuta HIGUCHI <y-higuchi@onlab.us>

The patch includes the following changes:
- New Floodlight I/O loop / state machine
- New switch/port handling
- New role management (incl. Role.EQUAL)
- Added Floodlight debug framework
- Updates to Controller.java
- Move to Loxigen's OpenflowJ library
- Added OF1.3 support
- Added support for different switches (via DriverManager)
- Updated ONOS modules to use new APIs
- Added and updated unit tests

Change-Id: Ic70a8d50f7136946193d2ba2e4dc0b4bfac5f599
diff --git a/src/main/java/net/floodlightcontroller/util/EnumBitmaps.java b/src/main/java/net/floodlightcontroller/util/EnumBitmaps.java
new file mode 100644
index 0000000..a7503eb
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/EnumBitmaps.java
@@ -0,0 +1,141 @@
+package net.floodlightcontroller.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
+ * }
+ * @author gregor
+ *
+ */
+public class 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/src/main/java/net/floodlightcontroller/util/LinkedHashSetWrapper.java b/src/main/java/net/floodlightcontroller/util/LinkedHashSetWrapper.java
new file mode 100644
index 0000000..65865c0
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/LinkedHashSetWrapper.java
@@ -0,0 +1,33 @@
+package net.floodlightcontroller.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.
+ * @author gregor
+ *
+ */
+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/src/main/java/net/floodlightcontroller/util/LoadMonitor.java b/src/main/java/net/floodlightcontroller/util/LoadMonitor.java
new file mode 100644
index 0000000..5b234cd
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/LoadMonitor.java
@@ -0,0 +1,275 @@
+/**
+ *    Copyright 2013, Big Switch Networks, Inc.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *    not use this file except in compliance with the License. You may obtain
+ *    a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ *    License for the specific language governing permissions and limitations
+ *    under the License.
+ **/
+
+package net.floodlightcontroller.util;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.slf4j.Logger;
+
+import net.floodlightcontroller.core.annotations.LogMessageDocs;
+import net.floodlightcontroller.core.annotations.LogMessageDoc;
+
+public class LoadMonitor implements Runnable {
+
+    public enum LoadLevel {
+        OK,
+        HIGH,
+        VERYHIGH,
+    }
+
+    public LoadLevel getLoadLevel() {
+        return loadlevel ;
+    }
+
+    public double getLoad() {
+        return load ;
+    }
+
+    public static final int LOADMONITOR_SAMPLING_INTERVAL = 1000; // mili-sec
+    public static final double THRESHOLD_HIGH = 0.90;
+    public static final double THRESHOLD_VERYHIGH = 0.95;
+    public static final int MAX_LOADED_ITERATIONS = 5;
+    public static final int MAX_LOAD_HISTORY = 5;
+
+    protected volatile double load;
+    protected volatile LoadLevel loadlevel;
+    protected int itersLoaded;
+
+    protected boolean isLinux;
+    protected int numcores;
+    protected int jiffyNanos;
+    protected long[] lastNanos;
+    protected long[] lastIdle;
+    protected Logger log;
+
+    public LoadMonitor(Logger log_) {
+        log = log_;
+        loadlevel = LoadLevel.OK;
+        load = 0.0;
+        itersLoaded = 0;
+
+        lastNanos = new long[MAX_LOAD_HISTORY];
+        lastIdle = new long[MAX_LOAD_HISTORY];
+        for (int i=0 ; i<MAX_LOAD_HISTORY ; i++) {
+            lastNanos[i] = 0L;
+            lastIdle[i] = 0L;
+        }
+
+        isLinux = System.getProperty("os.name").equals("Linux");
+        numcores = 1;
+        jiffyNanos = 10 * 1000 * 1000;
+        if (isLinux) {
+            try {
+                numcores = Integer.parseInt(
+                        this.runcmd("/usr/bin/nproc"));
+                jiffyNanos = (1000 * 1000 * 1000) / Integer.parseInt(
+                        this.runcmd("/usr/bin/getconf CLK_TCK"));
+            }
+            catch (NumberFormatException ex) {
+                if (log != null) {
+                        // Log message documented on runcmd function
+                    log.error("Exception in inializing load monitor ", ex);
+                }
+                else {
+                    ex.printStackTrace();
+                }
+            }
+        }
+    }
+
+    @Override
+    @LogMessageDocs({
+        @LogMessageDoc(
+            message="System under very heavy load, dropping some packet-ins",
+            explanation="We detcted that the system was under very heavy" +
+                        "  load, dropping some packet-ins temporarily"),
+        @LogMessageDoc(
+            message="System under heavy load, dropping some new flows",
+            explanation="We detcted that the system was under heavy load," +
+                        " dropping some new flows temporarily")
+    })
+    public void run() {
+        if (!isLinux) return;
+
+        long currNanos = System.nanoTime();
+        long currIdle = this.readIdle();
+        for (int i=0 ; i < (MAX_LOAD_HISTORY - 1) ; i++) {
+            lastNanos[i] = lastNanos[i+1];
+            lastIdle[i] = lastIdle[i+1];
+        }
+        lastNanos[MAX_LOAD_HISTORY - 1] = currNanos;
+        lastIdle[MAX_LOAD_HISTORY - 1] = currIdle;
+
+        if (itersLoaded >= MAX_LOADED_ITERATIONS) {
+            loadlevel = LoadLevel.OK;
+            itersLoaded = 0;
+            return;
+        }
+
+        long nanos = lastNanos[MAX_LOAD_HISTORY - 1] - lastNanos[0];
+        long idle = lastIdle[MAX_LOAD_HISTORY - 1] - lastIdle[0];
+        load =
+            1.0 - ((double)(idle * jiffyNanos) / (double)(nanos * numcores));
+
+        if (load > THRESHOLD_VERYHIGH) {
+            loadlevel = LoadLevel.VERYHIGH;
+            itersLoaded += 1;
+            String msg = "System under very heavy load, dropping packet-ins.";
+
+            if (log != null) {
+                log.error(msg);
+            }
+            else {
+                System.out.println(msg);
+            }
+            return;
+        }
+
+        if (load > THRESHOLD_HIGH) {
+            loadlevel = LoadLevel.HIGH;
+            itersLoaded += 1;
+            String msg = "System under heavy load, dropping new flows.";
+
+            if (log != null) {
+                log.error(msg);
+            }
+            else {
+                System.out.println(msg);
+            }
+            return;
+        }
+
+        loadlevel = LoadLevel.OK;
+        itersLoaded = 0;
+        return;
+    }
+
+    @LogMessageDoc(
+        message="Exception in reading load monitor params, using defaults",
+        explanation="There was an error in inializing load monitor's props," +
+                    " using default parameters")
+    protected String runcmd(String cmd) {
+        String line;
+        StringBuilder ret = new StringBuilder();
+        try {
+            Process p = Runtime.getRuntime().exec(cmd);
+            BufferedReader input =
+                new BufferedReader(
+                new InputStreamReader(p.getInputStream()));
+            while ((line = input.readLine()) != null) {
+                ret.append(line);
+            }
+            input.close();
+            p.waitFor();
+        }
+        catch (InterruptedException ex) {
+            if (log != null) {
+                log.error("Exception in inializing load monitor ", ex);
+            }
+            else {
+                ex.printStackTrace();
+            }
+        }
+        catch (IOException ex) {
+            if (log != null) {
+                log.error("Exception in inializing load monitor ", ex);
+            }
+            else {
+                ex.printStackTrace();
+            }
+        }
+        return ret.toString();
+
+    }
+
+    protected long readIdle() {
+        long idle = 0;
+        FileInputStream fs = null;
+        BufferedReader reader = null;
+        try {
+            try {
+                fs = new FileInputStream("/proc/stat");
+                reader = new BufferedReader(new InputStreamReader(fs));
+                String line = reader.readLine();
+                if (line == null) throw new IOException("Empty file");
+                idle = Long.parseLong(line.split("\\s+")[4]);
+            } finally {
+                if (reader != null)
+                    reader.close();
+                if (fs != null)
+                    fs.close();
+            }
+        } catch (IOException ex) {
+            log.error("Error reading idle time from /proc/stat", ex);
+        }
+        return idle;
+
+    }
+
+    public ScheduledFuture<?> startMonitoring(ScheduledExecutorService ses)
+    {
+        ScheduledFuture<?> monitorTask =
+            ses.scheduleAtFixedRate(
+                this, 0,
+                LOADMONITOR_SAMPLING_INTERVAL, TimeUnit.MILLISECONDS);
+        return monitorTask;
+    }
+
+    /*
+     * For testing
+     */
+    public ScheduledFuture<?> printMonitoring(ScheduledExecutorService ses)
+    {
+        final LoadMonitor mon = this;
+        ScheduledFuture<?> monitorTask =
+            ses.scheduleAtFixedRate(
+                new Runnable() {
+                    public void run() {
+                        System.out.println(mon.getLoad());
+                    }
+                }, LOADMONITOR_SAMPLING_INTERVAL/2,
+                LOADMONITOR_SAMPLING_INTERVAL, TimeUnit.MILLISECONDS);
+        return monitorTask;
+    }
+
+    public static void main(String[] args) {
+        final LoadMonitor monitor = new LoadMonitor(null);
+        final ScheduledExecutorService scheduler =
+            Executors.newScheduledThreadPool(1);
+        final ScheduledFuture<?> monitorTask =
+            monitor.startMonitoring(scheduler);
+        final ScheduledFuture<?> printTask =
+            monitor.printMonitoring(scheduler);
+
+        // Run the tasks for 2 minutes
+        scheduler.schedule(
+            new Runnable() {
+                public void run() {
+                    monitorTask.cancel(true);
+                    printTask.cancel(true);
+                }
+            }, 5*60, TimeUnit.SECONDS);
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java b/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java
index 5faf38e..90bee76 100644
--- a/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java
+++ b/src/main/java/net/floodlightcontroller/util/OFMessageDamper.java
@@ -133,7 +133,8 @@
                          FloodlightContext cntx, boolean flush)
             throws IOException {
         if (!msgTypesToCache.contains(msg.getType())) {
-            sw.write(msg, cntx);
+            // XXX S commenting out old message writes
+		//sw.write(msg, cntx);
             if (flush) {
                 sw.flush();
             }
@@ -145,7 +146,8 @@
             // entry exists in cache. Dampening.
             return false;
         } else {
-            sw.write(msg, cntx);
+            // XXX S commenting out old message writes
+		// sw.write(msg, cntx);
             if (flush) {
                 sw.flush();
             }
diff --git a/src/main/java/net/floodlightcontroller/util/OrderedCollection.java b/src/main/java/net/floodlightcontroller/util/OrderedCollection.java
new file mode 100644
index 0000000..e302a72
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/OrderedCollection.java
@@ -0,0 +1,15 @@
+package net.floodlightcontroller.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.
+ * @author gregor
+ *
+ * @param <E>
+ */
+public interface OrderedCollection<E> extends Collection<E> {
+
+}