Merge "Enable checkstyle rule for boolean return statement that can be simplified."
diff --git a/src/main/java/net/onrc/onos/api/packet/IPacketListener.java b/src/main/java/net/onrc/onos/api/packet/IPacketListener.java
new file mode 100644
index 0000000..000ed7a
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/packet/IPacketListener.java
@@ -0,0 +1,9 @@
+package net.onrc.onos.api.packet;
+
+import net.onrc.onos.core.packet.Ethernet;
+import net.onrc.onos.core.topology.Port;
+import net.onrc.onos.core.topology.Switch;
+
+public interface IPacketListener {
+    public void receive(Switch sw, Port inPort, Ethernet payload);
+}
diff --git a/src/main/java/net/onrc/onos/api/packet/IPacketService.java b/src/main/java/net/onrc/onos/api/packet/IPacketService.java
new file mode 100644
index 0000000..eaa372d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/api/packet/IPacketService.java
@@ -0,0 +1,21 @@
+package net.onrc.onos.api.packet;
+
+import java.util.List;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.onrc.onos.core.packet.Ethernet;
+import net.onrc.onos.core.topology.Port;
+
+public interface IPacketService extends IFloodlightService {
+    // packet ins
+    public void registerPacketListener(IPacketListener listener);
+
+    // packet outs
+    public void sendPacket(Port port, Ethernet eth);
+
+    public void sendPacket(List<Port> ports, Ethernet eth);
+
+    public void broadcastPacket(Ethernet eth);
+
+    public void broadcastPacket(Ethernet eth, Port inPort);
+}
diff --git a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
index d3db080..77703e5 100644
--- a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
@@ -19,7 +19,6 @@
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.util.MACAddress;
-import net.onrc.onos.apps.proxyarp.BroadcastPacketOutNotification;
 import net.onrc.onos.apps.proxyarp.IProxyArpService;
 import net.onrc.onos.core.datagrid.IDatagridService;
 import net.onrc.onos.core.datagrid.IEventChannel;
@@ -36,6 +35,7 @@
 import net.onrc.onos.core.intent.runtime.IPathCalcRuntimeService;
 import net.onrc.onos.core.intent.runtime.IntentStateList;
 import net.onrc.onos.core.packet.Ethernet;
+import net.onrc.onos.core.packetservice.BroadcastPacketOutNotification;
 import net.onrc.onos.core.registry.IControllerRegistryService;
 import net.onrc.onos.core.topology.Device;
 import net.onrc.onos.core.topology.INetworkGraphService;
diff --git a/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java b/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
index 017b260..d7e94cb 100644
--- a/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
+++ b/src/main/java/net/onrc/onos/apps/proxyarp/ProxyArpManager.java
@@ -32,6 +32,8 @@
 import net.onrc.onos.core.packet.ARP;
 import net.onrc.onos.core.packet.Ethernet;
 import net.onrc.onos.core.packet.IPv4;
+import net.onrc.onos.core.packetservice.BroadcastPacketOutNotification;
+import net.onrc.onos.core.packetservice.SinglePacketOutNotification;
 import net.onrc.onos.core.topology.Device;
 import net.onrc.onos.core.topology.INetworkGraphService;
 import net.onrc.onos.core.topology.NetworkGraph;
@@ -94,10 +96,10 @@
         @Override
         public void entryAdded(BroadcastPacketOutNotification value) {
             if (log.isTraceEnabled()) {
-                log.trace("entryAdded ip{}, sw {}, port {}, packet {}", value.getTargetAddress(), value.getInSwitch(), value.getInPort(), value.packet.length);
+                log.trace("entryAdded ip{}, sw {}, port {}, packet {}", value.getTargetAddress(), value.getInSwitch(), value.getInPort(), value.getPacketData().length);
             }
             BroadcastPacketOutNotification notification = (BroadcastPacketOutNotification) value;
-            broadcastArpRequestOutMyEdge(notification.packet,
+            broadcastArpRequestOutMyEdge(notification.getPacketData(),
                     notification.getInSwitch(),
                     notification.getInPort());
 
@@ -139,7 +141,7 @@
             log.debug("entryAdded");
             SinglePacketOutNotification notification =
                     (SinglePacketOutNotification) packetOutNotification;
-            sendArpRequestOutPort(notification.packet,
+            sendArpRequestOutPort(notification.getPacketData(),
                     notification.getOutSwitch(),
                     notification.getOutPort());
 
diff --git a/src/main/java/net/onrc/onos/apps/proxyarp/BroadcastPacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
similarity index 97%
rename from src/main/java/net/onrc/onos/apps/proxyarp/BroadcastPacketOutNotification.java
rename to src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
index 5f70cf1..cea27ae 100644
--- a/src/main/java/net/onrc/onos/apps/proxyarp/BroadcastPacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
@@ -1,4 +1,4 @@
-package net.onrc.onos.apps.proxyarp;
+package net.onrc.onos.core.packetservice;
 
 
 // TODO This class is too generic to be handled by ProxyArpService.
diff --git a/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java b/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java
new file mode 100644
index 0000000..b804a82
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java
@@ -0,0 +1,159 @@
+package net.onrc.onos.core.packetservice;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFMessageListener;
+import net.floodlightcontroller.core.IOFSwitch;
+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.onrc.onos.api.packet.IPacketListener;
+import net.onrc.onos.api.packet.IPacketService;
+import net.onrc.onos.core.packet.Ethernet;
+import net.onrc.onos.core.topology.INetworkGraphService;
+import net.onrc.onos.core.topology.NetworkGraph;
+import net.onrc.onos.core.topology.Port;
+import net.onrc.onos.core.topology.Switch;
+
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketIn;
+import org.openflow.protocol.OFType;
+
+public class PacketModule implements IOFMessageListener, IPacketService,
+                                     IFloodlightModule {
+
+    private final CopyOnWriteArrayList<IPacketListener> listeners;
+
+    private IFloodlightProviderService floodlightProvider;
+    private NetworkGraph networkGraph;
+
+    public PacketModule() {
+        listeners = new CopyOnWriteArrayList<>();
+    }
+
+    @Override
+    public void registerPacketListener(IPacketListener listener) {
+        listeners.addIfAbsent(listener);
+    }
+
+    @Override
+    public void sendPacket(Port port, Ethernet eth) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void sendPacket(List<Port> ports, Ethernet eth) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void broadcastPacket(Ethernet eth) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void broadcastPacket(Ethernet eth, Port inPort) {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public String getName() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean isCallbackOrderingPrereq(OFType type, String name) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isCallbackOrderingPostreq(OFType type, String name) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Command receive(IOFSwitch sw, OFMessage msg,
+            FloodlightContext cntx) {
+        if (!(msg instanceof OFPacketIn)) {
+            return Command.CONTINUE;
+        }
+
+        OFPacketIn pi = (OFPacketIn) msg;
+
+        Ethernet eth = IFloodlightProviderService.bcStore.
+                get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+
+        Switch networkGraphSwitch;
+        Port inPort;
+        try {
+            networkGraph.acquireReadLock();
+            networkGraphSwitch = networkGraph.getSwitch(sw.getId());
+            inPort = networkGraph.getPort(sw.getId(), (long) pi.getInPort());
+        } finally {
+            networkGraph.releaseReadLock();
+        }
+
+        if (networkGraphSwitch == null || inPort == null) {
+            return Command.CONTINUE;
+        }
+
+        for (IPacketListener listener : listeners) {
+            listener.receive(networkGraphSwitch, inPort, eth);
+        }
+
+        return Command.CONTINUE;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+        List<Class<? extends IFloodlightService>> services = new ArrayList<>();
+        services.add(IPacketService.class);
+        return services;
+    }
+
+    @Override
+    public Map<Class<? extends IFloodlightService>, IFloodlightService>
+            getServiceImpls() {
+        Map<Class<? extends IFloodlightService>, IFloodlightService>
+                serviceImpls = new HashMap<>();
+        serviceImpls.put(IPacketService.class, this);
+        return serviceImpls;
+    }
+
+    @Override
+    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+        List<Class<? extends IFloodlightService>> dependencies = new ArrayList<>();
+        dependencies.add(IFloodlightProviderService.class);
+        dependencies.add(INetworkGraphService.class);
+        return dependencies;
+    }
+
+    @Override
+    public void init(FloodlightModuleContext context)
+            throws FloodlightModuleException {
+        floodlightProvider =
+                context.getServiceImpl(IFloodlightProviderService.class);
+        networkGraph = context.getServiceImpl(INetworkGraphService.class)
+                .getNetworkGraph();
+    }
+
+    @Override
+    public void startUp(FloodlightModuleContext context) {
+        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
+    }
+}
diff --git a/src/main/java/net/onrc/onos/apps/proxyarp/PacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
similarity index 80%
rename from src/main/java/net/onrc/onos/apps/proxyarp/PacketOutNotification.java
rename to src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
index a3cbb28..30e3986 100644
--- a/src/main/java/net/onrc/onos/apps/proxyarp/PacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/PacketOutNotification.java
@@ -1,4 +1,4 @@
-package net.onrc.onos.apps.proxyarp;
+package net.onrc.onos.core.packetservice;
 
 import java.io.Serializable;
 import java.util.Arrays;
@@ -13,7 +13,7 @@
 
     private static final long serialVersionUID = 1L;
 
-    protected final byte[] packet;
+    private final byte[] packet;
 
     /**
      * Class constructor.
@@ -27,4 +27,8 @@
     public PacketOutNotification(byte[] packet) {
         this.packet = Arrays.copyOf(packet, packet.length);
     }
+
+    public byte[] getPacketData() {
+        return Arrays.copyOf(packet, packet.length);
+    }
 }
diff --git a/src/main/java/net/onrc/onos/apps/proxyarp/SinglePacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
similarity index 97%
rename from src/main/java/net/onrc/onos/apps/proxyarp/SinglePacketOutNotification.java
rename to src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
index ff5ab87..4e9f47d 100644
--- a/src/main/java/net/onrc/onos/apps/proxyarp/SinglePacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/SinglePacketOutNotification.java
@@ -1,4 +1,4 @@
-package net.onrc.onos.apps.proxyarp;
+package net.onrc.onos.core.packetservice;
 
 
 // TODO This class is too generic to be handled by ProxyArpService.
diff --git a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
index 8c77fc8..e229d30 100644
--- a/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
+++ b/src/main/java/net/onrc/onos/core/util/serializers/KryoFactory.java
@@ -8,8 +8,6 @@
 
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.apps.proxyarp.ArpReplyNotification;
-import net.onrc.onos.apps.proxyarp.BroadcastPacketOutNotification;
-import net.onrc.onos.apps.proxyarp.SinglePacketOutNotification;
 import net.onrc.onos.core.devicemanager.OnosDevice;
 import net.onrc.onos.core.intent.ConstrainedShortestPathIntent;
 import net.onrc.onos.core.intent.ErrorIntent;
@@ -19,6 +17,8 @@
 import net.onrc.onos.core.intent.PathIntent;
 import net.onrc.onos.core.intent.ShortestPathIntent;
 import net.onrc.onos.core.intent.runtime.IntentStateList;
+import net.onrc.onos.core.packetservice.BroadcastPacketOutNotification;
+import net.onrc.onos.core.packetservice.SinglePacketOutNotification;
 import net.onrc.onos.core.topology.DeviceEvent;
 import net.onrc.onos.core.topology.LinkEvent;
 import net.onrc.onos.core.topology.Path;
@@ -50,6 +50,7 @@
 import net.onrc.onos.core.util.Switch;
 // import net.onrc.onos.core.util.SwitchPort;
 
+
 import com.esotericsoftware.kryo.Kryo;
 
 /**
diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
index dff2708..83e6b68 100644
--- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
+++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
@@ -21,3 +21,4 @@
 net.onrc.onos.core.topology.NetworkGraphModule
 net.onrc.onos.core.intent.runtime.PathCalcRuntimeModule
 net.onrc.onos.core.intent.runtime.PlanInstallModule
+net.onrc.onos.core.packetservice.PacketModule