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/onrc/onos/core/topology/TopologyPublisher.java b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
index ed450f2..8b77745 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
@@ -9,20 +9,20 @@
 import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IOFSwitch.PortChangeType;
+import net.floodlightcontroller.core.IOFSwitchListener;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.SingletonTask;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
-import net.onrc.onos.api.registry.ILocalSwitchMastershipListener;
 import net.onrc.onos.core.hostmanager.Host;
 import net.onrc.onos.core.hostmanager.IHostListener;
 import net.onrc.onos.core.hostmanager.IHostService;
 import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryListener;
 import net.onrc.onos.core.linkdiscovery.ILinkDiscoveryService;
 import net.onrc.onos.core.linkdiscovery.Link;
-import net.onrc.onos.core.main.IOFSwitchPortListener;
 import net.onrc.onos.core.registry.IControllerRegistryService;
 import net.onrc.onos.core.registry.IControllerRegistryService.ControlChangeCallback;
 import net.onrc.onos.core.registry.RegistryException;
@@ -30,8 +30,8 @@
 import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
 
-import org.openflow.protocol.OFPhysicalPort;
-import org.openflow.util.HexString;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -40,12 +40,10 @@
  * discovery modules. These events are reformatted and relayed to the in-memory
  * topology instance.
  */
-public class TopologyPublisher implements /*IOFSwitchListener,*/
-        IOFSwitchPortListener,
+public class TopologyPublisher implements IOFSwitchListener,
         ILinkDiscoveryListener,
         IFloodlightModule,
-        IHostListener,
-        ILocalSwitchMastershipListener {
+        IHostListener {
     private static final Logger log =
             LoggerFactory.getLogger(TopologyPublisher.class);
 
@@ -65,8 +63,8 @@
     private SingletonTask cleanupTask;
 
     /**
-     * Cleanup old switches from the topology. Old switches are those
-     * which have no controller in the registry.
+     * Cleanup old switches from the topology. Old switches are those which have
+     * no controller in the registry.
      */
     private class SwitchCleanup implements ControlChangeCallback, Runnable {
         @Override
@@ -97,7 +95,8 @@
             if (log.isTraceEnabled()) {
                 log.trace("Checking for inactive switches");
             }
-            // For each switch check if a controller exists in controller registry
+            // For each switch check if a controller exists in controller
+            // registry
             for (Switch sw : switches) {
                 // FIXME How to handle case where Switch has never been
                 // registered to ZK
@@ -120,10 +119,10 @@
 
         /**
          * Second half of the switch cleanup operation. If the registry grants
-         * control of a switch, we can be sure no other instance is writing
-         * this switch to the topology, so we can remove it now.
-         *
-         * @param dpid       the dpid of the switch we requested control for
+         * control of a switch, we can be sure no other instance is writing this
+         * switch to the topology, so we can remove it now.
+         * <p>
+         * @param dpid the dpid of the switch we requested control for
          * @param hasControl whether we got control or not
          */
         @Override
@@ -150,7 +149,7 @@
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
         linkEvent.createStringAttribute(TopologyElement.TYPE,
-                                        TopologyElement.TYPE_PACKET_LAYER);
+                TopologyElement.TYPE_PACKET_LAYER);
         linkEvent.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
                 ConfigState.NOT_CONFIGURED.toString());
         linkEvent.createStringAttribute(TopologyElement.ELEMENT_ADMIN_STATUS,
@@ -177,51 +176,173 @@
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
         linkEvent.createStringAttribute(TopologyElement.TYPE,
-                                        TopologyElement.TYPE_PACKET_LAYER);
+                TopologyElement.TYPE_PACKET_LAYER);
         linkEvent.freeze();
 
         if (!registryService.hasControl(link.getDst())) {
             // Don't process or send a link event if we're not master for the
             // destination switch
-            log.debug("Not the master for dst switch {}. Suppressed link remove event {}.",
+            log.debug(
+                    "Not the master for dst switch {}. Suppressed link remove event {}.",
                     link.getDst(), linkEvent);
             return;
         }
         topologyDiscoveryInterface.removeLinkDiscoveryEvent(linkEvent);
     }
 
+    /* *****************
+     * IOFSwitchListener
+     * *****************/
+
     @Override
-    public void switchPortAdded(Long switchId, OFPhysicalPort port) {
+    public void switchActivatedMaster(long swId) {
+        IOFSwitch sw = floodlightProvider.getSwitch(swId);
+        final Dpid dpid = new Dpid(swId);
+        if (sw == null) {
+            log.warn("Added switch not available {} ", dpid);
+            return;
+        }
+
+        controllerRoleChanged(dpid, Role.MASTER);
+
+        SwitchEvent switchEvent = new SwitchEvent(dpid);
+        // FIXME should be merging, with existing attrs, etc..
+        // TODO define attr name as constant somewhere.
+        // TODO populate appropriate attributes.
+        switchEvent.createStringAttribute(TopologyElement.TYPE,
+                TopologyElement.TYPE_PACKET_LAYER);
+        switchEvent.createStringAttribute("ConnectedSince",
+                sw.getConnectedSince().toString());
+        switchEvent.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
+                ConfigState.NOT_CONFIGURED.toString());
+        switchEvent.createStringAttribute(TopologyElement.ELEMENT_ADMIN_STATUS,
+                AdminStatus.ACTIVE.toString());
+        switchEvent.freeze();
+        // TODO Not very robust
+        if (!registryService.hasControl(swId)) {
+            log.debug("Not the master for switch {}. Suppressed switch add event {}.",
+                    dpid, switchEvent);
+            return;
+        }
+        List<PortEvent> portEvents = new ArrayList<PortEvent>();
+        for (OFPortDesc port : sw.getPorts()) {
+            PortEvent portEvent = new PortEvent(dpid,
+                    new PortNumber(port.getPortNo().getShortPortNumber()));
+            // FIXME should be merging, with existing attrs, etc..
+            // TODO define attr name as constant somewhere.
+            // TODO populate appropriate attributes.
+            portEvent.createStringAttribute("name", port.getName());
+            portEvent.createStringAttribute(TopologyElement.TYPE,
+                    TopologyElement.TYPE_PACKET_LAYER);
+            portEvent.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
+                    ConfigState.NOT_CONFIGURED.toString());
+            portEvent.createStringAttribute(TopologyElement.ELEMENT_ADMIN_STATUS,
+                    AdminStatus.ACTIVE.toString());
+
+            portEvent.freeze();
+            portEvents.add(portEvent);
+        }
+        topologyDiscoveryInterface.putSwitchDiscoveryEvent(switchEvent, portEvents);
+
+        for (OFPortDesc port : sw.getPorts()) {
+            // Allow links to be discovered on this port now that it's
+            // in the database
+            linkDiscovery.enableDiscoveryOnPort(sw.getId(),
+                    port.getPortNo().getShortPortNumber());
+        }
+    }
+
+    @Override
+    public void switchActivatedEqual(long swId) {
+        final Dpid dpid = new Dpid(swId);
+        controllerRoleChanged(dpid, Role.EQUAL);
+    }
+
+    @Override
+    public void switchMasterToEqual(long swId) {
+        final Dpid dpid = new Dpid(swId);
+        controllerRoleChanged(dpid, Role.EQUAL);
+    }
+
+    @Override
+    public void switchEqualToMaster(long swId) {
+        // for now treat as switchActivatedMaster
+        switchActivatedMaster(swId);
+    }
+
+    @Override
+    public void switchDisconnected(long swId) {
+        final Dpid dpid = new Dpid(swId);
+
+        log.debug("Local switch disconnected: dpid = {} role = {}", dpid);
+
+        Role role = Role.SLAVE; // TODO: Should be Role.UNKNOWN
+
+        MastershipEvent mastershipEvent =
+                new MastershipEvent(dpid, registryService.getOnosInstanceId(),
+                        role);
+        // FIXME should be merging, with existing attrs, etc..
+        // TODO define attr name as constant somewhere.
+        // TODO populate appropriate attributes.
+        mastershipEvent.createStringAttribute(TopologyElement.TYPE,
+                TopologyElement.TYPE_ALL_LAYERS);
+        mastershipEvent.freeze();
+        topologyDiscoveryInterface.removeSwitchMastershipEvent(mastershipEvent);
+    }
+
+    @Override
+    public void switchPortChanged(long swId, OFPortDesc port,
+            PortChangeType changeType) {
+        switch (changeType) {
+        case ADD:
+            switchPortAdded(swId, port);
+            break;
+        case DELETE:
+            switchPortRemoved(swId, port);
+            break;
+        case DOWN:
+        case UP:
+        case OTHER_UPDATE:
+        default:
+            // XXX S what is the right set of port change handlers?
+            log.debug("Topology publisher does not handle these port updates: {}",
+                        changeType);
+        }
+    }
+
+    private void switchPortAdded(long switchId, OFPortDesc port) {
         final Dpid dpid = new Dpid(switchId);
-        PortEvent portEvent = new PortEvent(dpid, new PortNumber(port.getPortNumber()));
+        PortEvent portEvent = new PortEvent(dpid,
+                new PortNumber(port.getPortNo().getShortPortNumber()));
         // FIXME should be merging, with existing attrs, etc..
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
         portEvent.createStringAttribute(TopologyElement.TYPE,
-                                        TopologyElement.TYPE_PACKET_LAYER);
+                TopologyElement.TYPE_PACKET_LAYER);
         portEvent.createStringAttribute("name", port.getName());
 
         portEvent.freeze();
 
         if (registryService.hasControl(switchId)) {
             topologyDiscoveryInterface.putPortDiscoveryEvent(portEvent);
-            linkDiscovery.enableDiscoveryOnPort(switchId, port.getPortNumber());
+            linkDiscovery.enableDiscoveryOnPort(switchId,
+                    port.getPortNo().getShortPortNumber());
         } else {
             log.debug("Not the master for switch {}. Suppressed port add event {}.",
                     new Dpid(switchId), portEvent);
         }
     }
 
-    @Override
-    public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
+    private void switchPortRemoved(long switchId, OFPortDesc port) {
         final Dpid dpid = new Dpid(switchId);
 
-        PortEvent portEvent = new PortEvent(dpid, new PortNumber(port.getPortNumber()));
+        PortEvent portEvent = new PortEvent(dpid, new PortNumber(
+                port.getPortNo().getShortPortNumber()));
         // FIXME should be merging, with existing attrs, etc..
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
         portEvent.createStringAttribute(TopologyElement.TYPE,
-                                        TopologyElement.TYPE_PACKET_LAYER);
+                TopologyElement.TYPE_PACKET_LAYER);
         portEvent.createStringAttribute("name", port.getName());
 
         portEvent.freeze();
@@ -235,70 +356,8 @@
     }
 
     @Override
-    public void addedSwitch(IOFSwitch sw) {
-        final Dpid dpid = new Dpid(sw.getId());
-        SwitchEvent switchEvent = new SwitchEvent(dpid);
-        // FIXME should be merging, with existing attrs, etc..
-        // TODO define attr name as constant somewhere.
-        // TODO populate appropriate attributes.
-        switchEvent.createStringAttribute(TopologyElement.TYPE,
-                                          TopologyElement.TYPE_PACKET_LAYER);
-        switchEvent.createStringAttribute("ConnectedSince",
-                sw.getConnectedSince().toString());
-        switchEvent.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
-                ConfigState.NOT_CONFIGURED.toString());
-        switchEvent.createStringAttribute(TopologyElement.ELEMENT_ADMIN_STATUS,
-                AdminStatus.ACTIVE.toString());
-        switchEvent.freeze();
-
-        // TODO Not very robust
-        if (!registryService.hasControl(sw.getId())) {
-            log.debug("Not the master for switch {}. Suppressed switch add event {}.",
-                    dpid, switchEvent);
-            return;
-        }
-
-        List<PortEvent> portEvents = new ArrayList<PortEvent>();
-        for (OFPhysicalPort port : sw.getPorts()) {
-            PortEvent portEvent = new PortEvent(dpid, new PortNumber(port.getPortNumber()));
-            // FIXME should be merging, with existing attrs, etc..
-            // TODO define attr name as constant somewhere.
-            // TODO populate appropriate attributes.
-            portEvent.createStringAttribute("name", port.getName());
-            portEvent.createStringAttribute(TopologyElement.TYPE,
-                                            TopologyElement.TYPE_PACKET_LAYER);
-            portEvent.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
-                    ConfigState.NOT_CONFIGURED.toString());
-            portEvent.createStringAttribute(TopologyElement.ELEMENT_ADMIN_STATUS,
-                    AdminStatus.ACTIVE.toString());
-
-            portEvent.freeze();
-            portEvents.add(portEvent);
-        }
-        topologyDiscoveryInterface
-                .putSwitchDiscoveryEvent(switchEvent, portEvents);
-
-        for (OFPhysicalPort port : sw.getPorts()) {
-            // Allow links to be discovered on this port now that it's
-            // in the database
-            linkDiscovery.enableDiscoveryOnPort(sw.getId(), port.getPortNumber());
-        }
-    }
-
-    @Override
-    public void removedSwitch(IOFSwitch sw) {
-        // We don't use this event - switch remove is done by cleanup thread
-    }
-
-    @Override
-    public void switchPortChanged(Long switchId) {
-        // We don't use this event
-    }
-
-    @Override
     public String getName() {
-        // TODO Auto-generated method stub
-        return null;
+        return "topologyPublisher";
     }
 
     /* *****************
@@ -312,13 +371,13 @@
 
     @Override
     public Map<Class<? extends IFloodlightService>, IFloodlightService>
-    getServiceImpls() {
+            getServiceImpls() {
         return null;
     }
 
     @Override
     public Collection<Class<? extends IFloodlightService>>
-    getModuleDependencies() {
+            getModuleDependencies() {
         Collection<Class<? extends IFloodlightService>> l =
                 new ArrayList<Class<? extends IFloodlightService>>();
         l.add(IFloodlightProviderService.class);
@@ -339,8 +398,6 @@
         hostService = context.getServiceImpl(IHostService.class);
 
         topologyService = context.getServiceImpl(ITopologyService.class);
-
-        floodlightProvider.addLocalSwitchMastershipListener(this);
     }
 
     @Override
@@ -393,41 +450,23 @@
     public void hostRemoved(Host host) {
         log.debug("Called onosDeviceRemoved");
         HostEvent event = new HostEvent(host.getMacAddress());
-        //XXX shouldn't we be setting attachment points?
+        // XXX shouldn't we be setting attachment points?
         event.freeze();
         topologyDiscoveryInterface.removeHostDiscoveryEvent(event);
     }
 
-    @Override
-    public void controllerRoleChanged(Dpid dpid, Role role) {
-        log.debug("Local switch controller mastership role changed: dpid = {} role = {}", dpid, role);
+    private void controllerRoleChanged(Dpid dpid, Role role) {
+        log.debug("Local switch controller mastership role changed: dpid = {} role = {}",
+                dpid, role);
         MastershipEvent mastershipEvent =
-            new MastershipEvent(dpid, registryService.getOnosInstanceId(),
-                                role);
+                new MastershipEvent(dpid, registryService.getOnosInstanceId(),
+                        role);
         // FIXME should be merging, with existing attrs, etc..
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
         mastershipEvent.createStringAttribute(TopologyElement.TYPE,
-                                              TopologyElement.TYPE_ALL_LAYERS);
+                TopologyElement.TYPE_ALL_LAYERS);
         mastershipEvent.freeze();
         topologyDiscoveryInterface.putSwitchMastershipEvent(mastershipEvent);
     }
-
-    @Override
-    public void switchDisconnected(Dpid dpid) {
-        log.debug("Local switch disconnected: dpid = {} role = {}", dpid);
-
-        Role role = Role.SLAVE;         // TODO: Should be Role.UNKNOWN
-
-        MastershipEvent mastershipEvent =
-            new MastershipEvent(dpid, registryService.getOnosInstanceId(),
-                                role);
-        // FIXME should be merging, with existing attrs, etc..
-        // TODO define attr name as constant somewhere.
-        // TODO populate appropriate attributes.
-        mastershipEvent.createStringAttribute(TopologyElement.TYPE,
-                                              TopologyElement.TYPE_ALL_LAYERS);
-        mastershipEvent.freeze();
-        topologyDiscoveryInterface.removeSwitchMastershipEvent(mastershipEvent);
-    }
 }