Basic IGMP skeleton app is ready to go.  IGMP packet type,
serialization and deserialization has been moved
to the ONOS core.

Change-Id: I5c70d1e035e468eddf3e6b4ff6d1efc72e242fa2
diff --git a/igmp/pom.xml b/igmp/pom.xml
new file mode 100644
index 0000000..2ecd0b9
--- /dev/null
+++ b/igmp/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2014 Open Networking Laboratory
+  ~
+  ~ 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.
+  -->
+<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>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-app-samples</artifactId>
+        <version>1.3.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>onos-app-igmp</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>Internet Group Message Protocol</description>
+
+    <properties>
+        <onos.app.name>org.onosproject.igmp</onos.app.name>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-cli</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-osgi</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- This is needed by ComponentContext, used for tunable configuration -->
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <version>1.9.8</version>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>
+                            ${project.groupId}.${project.artifactId}
+                        </Bundle-SymbolicName>
+                        <Import-Package>
+                            org.slf4j,
+                            org.osgi.framework,
+                            org.apache.commons.lang.math.*,
+                            com.google.common.*,
+                            org.onlab.packet.*,
+                            org.onlab.rest.*,
+                            org.onosproject.*,
+                            org.onosproject.mfwd.impl.*;
+                            org.onlab.util.*,
+                            org.jboss.netty.util.*
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.5.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/igmp/src/main/java/org/onosproject/igmp/impl/IGMPComponent.java b/igmp/src/main/java/org/onosproject/igmp/impl/IGMPComponent.java
new file mode 100644
index 0000000..ae539c6
--- /dev/null
+++ b/igmp/src/main/java/org/onosproject/igmp/impl/IGMPComponent.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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 org.onosproject.igmp.impl;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+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.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.IGMP;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketPriority;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+import org.slf4j.Logger;
+
+/**
+ * Internet Group Management Protocol.
+ */
+@Component(immediate = true)
+public class IGMPComponent {
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected PacketService packetService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    private IGMPPacketProcessor processor = new IGMPPacketProcessor();
+    private static ApplicationId appId;
+
+    @Activate
+    public void activate() {
+        appId = coreService.registerApplication("org.onosproject.igmp");
+
+        packetService.addProcessor(processor, PacketProcessor.director(1));
+
+        // Build a traffic selector for all multicast traffic
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        selector.matchEthType(Ethernet.TYPE_IPV4);
+        selector.matchIPProtocol(IPv4.PROTOCOL_IGMP);
+        packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
+
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        packetService.removeProcessor(processor);
+        processor = null;
+        log.info("Stopped");
+    }
+
+    /**
+     * Packet processor responsible for handling IGMP packets.
+     */
+    private class IGMPPacketProcessor implements PacketProcessor {
+
+        @Override
+        public void process(PacketContext context) {
+            // Stop processing if the packet has been handled, since we
+            // can't do any more to it.
+            if (context.isHandled()) {
+                return;
+            }
+
+            InboundPacket pkt = context.inPacket();
+            Ethernet ethPkt = pkt.parsed();
+            if (ethPkt == null) {
+                return;
+            }
+
+            /*
+             * IPv6 MLD packets are handled by ICMP6. We'll only deal
+             * with IPv4.
+             */
+            if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
+                return;
+            }
+
+            IPv4 ip = (IPv4) ethPkt.getPayload();
+            IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
+            IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
+            log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() +
+                    "\tingress port: " + context.inPacket().receivedFrom().toString());
+
+            if (ip.getProtocol() != IPv4.PROTOCOL_IGMP) {
+                log.error("IGMP Picked up a non IGMP packet.");
+                return;
+            }
+
+            IpPrefix mcast = IpPrefix.valueOf("224.0.0.0/4");
+            if (!mcast.contains(gaddr)) {
+                log.error("IGMP Picked up a non multicast packet.");
+                return;
+            }
+
+            if (mcast.contains(saddr)) {
+                log.error("IGMP Picked up a packet with a multicast source address.");
+                return;
+            }
+            IpPrefix spfx = IpPrefix.valueOf(saddr, 32);
+            IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32);
+
+            IGMP igmp = (IGMP) ip.getPayload();
+            switch (igmp.getIgmpType()) {
+
+                case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT:
+                    IGMPProcessMembership.processMembership(igmp, pkt.receivedFrom());
+                    break;
+
+                case IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY:
+                    IGMPProcessQuery.processQuery(igmp, pkt.receivedFrom());
+                    break;
+
+                case IGMP.TYPE_IGMPV1_MEMBERSHIP_REPORT:
+                case IGMP.TYPE_IGMPV2_MEMBERSHIP_REPORT:
+                case IGMP.TYPE_IGMPV2_LEAVE_GROUP:
+                    log.debug("IGMP version 1 & 2 message types are not currently supported. Message type: " +
+                            igmp.getIgmpType());
+                    break;
+
+                default:
+                    log.debug("Unkown IGMP message type: " + igmp.getIgmpType());
+                    break;
+            }
+        }
+    }
+}
diff --git a/igmp/src/main/java/org/onosproject/igmp/impl/IGMPProcessMembership.java b/igmp/src/main/java/org/onosproject/igmp/impl/IGMPProcessMembership.java
new file mode 100644
index 0000000..4c08a74
--- /dev/null
+++ b/igmp/src/main/java/org/onosproject/igmp/impl/IGMPProcessMembership.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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 org.onosproject.igmp.impl;
+
+import org.onlab.packet.IGMP;
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Process an IGMP Membership Report.
+ */
+public final class IGMPProcessMembership {
+
+    // Hide the default constructor.
+    private IGMPProcessMembership() {
+    }
+
+    /**
+     * Process the IGMP Membership report.
+     *
+     * @param igmp the deserialized IGMP message.
+     */
+    public static void processMembership(IGMP igmp, ConnectPoint recievedFrom) {
+    }
+
+}
diff --git a/igmp/src/main/java/org/onosproject/igmp/impl/IGMPProcessQuery.java b/igmp/src/main/java/org/onosproject/igmp/impl/IGMPProcessQuery.java
new file mode 100644
index 0000000..8407bb1
--- /dev/null
+++ b/igmp/src/main/java/org/onosproject/igmp/impl/IGMPProcessQuery.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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 org.onosproject.igmp.impl;
+
+import org.onlab.packet.IGMP;
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Process IGMP Query messages.
+ */
+public final class IGMPProcessQuery {
+
+    // Hide the default constructor.
+    private IGMPProcessQuery() {
+    }
+
+    /**
+     * Process the IGMP Membership Query message.
+     *
+     * @param igmp The deserialzed IGMP message
+     */
+    public static void processQuery(IGMP igmp, ConnectPoint receivedFrom) {
+    }
+
+}
diff --git a/pom.xml b/pom.xml
index 4281fee..8aae095 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,7 @@
         <module>database-perf</module>
         <module>tvue</module>
         <module>mfwd</module>
+	<module>igmp</module>
         <module>flowtest</module>
     </modules>