Refactored the forwarding module to use the new packet API.

It now uses PacketService for both receiving packet-ins and sending
packet-outs, so there is now no dependency on FloodlightProvider or
FlowPusher.

Fixed a bug where the packet module wasn't sending packet-outs correctly.

Change-Id: If738797cdcebabfed975875daf4b40df99226585
diff --git a/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
index 3e098ed..bf5c700 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
@@ -2,6 +2,9 @@
 
 import java.util.Map;
 
+import net.onrc.onos.core.topology.NetworkGraph;
+import net.onrc.onos.core.topology.Port;
+
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 
@@ -75,12 +78,25 @@
     }
 
     @Override
-    public Multimap<Long, Short> calculateOutPorts(Multimap<Long, Short> localSwitches) {
+    public Multimap<Long, Short> calculateOutPorts(
+            Multimap<Long, Short> localPorts, NetworkGraph networkGraph) {
         Multimap<Long, Short> outPorts = HashMultimap.create();
 
-        for (Map.Entry<Long, Short> entry : localSwitches.entries()) {
-            if (!entry.getKey().equals(inSwitch) ||
-                    !entry.getValue().equals(inPort)) {
+        for (Map.Entry<Long, Short> entry : localPorts.entries()) {
+            Port globalPort;
+            networkGraph.acquireReadLock();
+            try {
+                globalPort = networkGraph.getPort(entry.getKey(),
+                    entry.getValue().longValue());
+            } finally {
+                networkGraph.releaseReadLock();
+            }
+
+            if ((!entry.getKey().equals(inSwitch) ||
+                    !entry.getValue().equals(inPort)) &&
+                    globalPort != null &&
+                    globalPort.getOutgoingLink() == null) {
+
                 outPorts.put(entry.getKey(), entry.getValue());
             }
         }
diff --git a/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java b/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java
index 27bfbb5..1e3cae6 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java
@@ -67,8 +67,14 @@
 
         @Override
         public void entryAdded(PacketOutNotification value) {
+            Multimap<Long, Short> localPorts = HashMultimap.create();
+            for (IOFSwitch sw : floodlightProvider.getSwitches().values()) {
+                for (OFPhysicalPort port : sw.getEnabledPorts()) {
+                    localPorts.put(sw.getId(), port.getPortNumber());
+                }
+            }
             Multimap<Long, Short> outPorts = value.calculateOutPorts(
-                    findLocalEdgePorts());
+                    localPorts, networkGraph);
             sendPacketToSwitches(outPorts, value.getPacketData());
         }
 
@@ -164,6 +170,8 @@
         }
 
         if (networkGraphSwitch == null || inPort == null) {
+            // We can't send packets for switches or ports that aren't in the
+            // network graph yet
             return Command.CONTINUE;
         }
 
@@ -221,21 +229,6 @@
                 PacketOutNotification.class);
     }
 
-    private Multimap<Long, Short> findLocalEdgePorts() {
-        Multimap<Long, Short> edgePorts = HashMultimap.create();
-        Map<Long, IOFSwitch> localSwitches = floodlightProvider.getSwitches();
-        for (IOFSwitch sw : localSwitches.values()) {
-            for (OFPhysicalPort localPort : sw.getEnabledPorts()) {
-                Port globalPort =
-                        networkGraph.getPort(sw.getId(), (long) localPort.getPortNumber());
-                if (globalPort.getOutgoingLink() == null) {
-                    edgePorts.put(sw.getId(), localPort.getPortNumber());
-                }
-            }
-        }
-        return edgePorts;
-    }
-
     private void sendPacketToSwitches(Multimap<Long, Short> outPorts,
             byte[] packetData) {
         for (Long dpid : outPorts.keySet()) {
diff --git a/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
index 8fe8efe..d95ddf2 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
@@ -3,6 +3,8 @@
 import java.io.Serializable;
 import java.util.Arrays;
 
+import net.onrc.onos.core.topology.NetworkGraph;
+
 import com.google.common.collect.Multimap;
 
 /**
@@ -51,11 +53,12 @@
      * calculate that list, given the list of edge ports controlled by this
      * instance.
      *
-     * @param localSwitches the map of locally-controlled edge ports
+     * @param localPorts the map of locally-controlled ports
+     * @param networkGraph an instance of the global network graph
      * @return a multimap of ports that the packet should be sent out,
      * in the form
      * {@code {dpid1 => {portnum1, portnum2, ...}, dpid2 => {portnum1}, ...}}
      */
     public abstract Multimap<Long, Short> calculateOutPorts(
-            Multimap<Long, Short> localEdgePorts);
+            Multimap<Long, Short> localPorts, NetworkGraph networkGraph);
 }
diff --git a/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
index e6260e0..cd604ea 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
@@ -1,5 +1,7 @@
 package net.onrc.onos.core.packetservice;
 
+import net.onrc.onos.core.topology.NetworkGraph;
+
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 
@@ -14,6 +16,12 @@
     private final long outSwitch;
     private final short outPort;
 
+    protected SinglePacketOutNotification() {
+        address = 0;
+        outSwitch = 0;
+        outPort = 0;
+    }
+
     /**
      * Class constructor.
      *
@@ -60,10 +68,11 @@
     }
 
     @Override
-    public Multimap<Long, Short> calculateOutPorts(Multimap<Long, Short> localSwitches) {
+    public Multimap<Long, Short> calculateOutPorts(
+            Multimap<Long, Short> localPorts, NetworkGraph networkGraph) {
         Multimap<Long, Short> outPorts = HashMultimap.create();
 
-        if (localSwitches.containsEntry(outSwitch, outPort)) {
+        if (localPorts.containsEntry(outSwitch, outPort)) {
             outPorts.put(outSwitch, outPort);
         }
 
diff --git a/src/main/java/net/onrc/onos/core/topology/Switch.java b/src/main/java/net/onrc/onos/core/topology/Switch.java
index d9796be..690cea8 100644
--- a/src/main/java/net/onrc/onos/core/topology/Switch.java
+++ b/src/main/java/net/onrc/onos/core/topology/Switch.java
@@ -15,7 +15,6 @@
 
     public Port getPort(Long number);
 
-
     // Graph traversal API
     // XXX What is the Definition of neighbor? Link exist in both direction or one-way is sufficient to be a neighbor, etc.
     public Iterable<Switch> getNeighbors();