Fixes to the IGMP app to process group membership reports

Change-Id: I7a478011caadb8250f6a25b5fb5a820485e593b6
diff --git a/apps/igmp/src/main/java/org/onosproject/igmp/IGMPProcessMembership.java b/apps/igmp/src/main/java/org/onosproject/igmp/IGMPProcessMembership.java
deleted file mode 100644
index 0065af4..0000000
--- a/apps/igmp/src/main/java/org/onosproject/igmp/IGMPProcessMembership.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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;
-
-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.
-     * @param receivedFrom the ConnectPoint this message came from.
-     */
-    public static void processMembership(IGMP igmp, ConnectPoint receivedFrom) {
-    }
-
-}
diff --git a/apps/igmp/src/main/java/org/onosproject/igmp/IGMPProcessQuery.java b/apps/igmp/src/main/java/org/onosproject/igmp/IGMPProcessQuery.java
deleted file mode 100644
index a5ddbf3..0000000
--- a/apps/igmp/src/main/java/org/onosproject/igmp/IGMPProcessQuery.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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;
-
-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
-     * @param receivedFrom the ConnectPoint this message came from.
-     */
-    public static void processQuery(IGMP igmp, ConnectPoint receivedFrom) {
-    }
-
-}
diff --git a/apps/igmp/src/main/java/org/onosproject/igmp/IgmpSnoop.java b/apps/igmp/src/main/java/org/onosproject/igmp/IgmpSnoop.java
index 3ade419..a0e2aeb 100644
--- a/apps/igmp/src/main/java/org/onosproject/igmp/IgmpSnoop.java
+++ b/apps/igmp/src/main/java/org/onosproject/igmp/IgmpSnoop.java
@@ -24,6 +24,7 @@
 import org.onlab.packet.EthType;
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.IGMP;
+import org.onlab.packet.IGMPMembership;
 import org.onlab.packet.IPv4;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.IpAddress;
@@ -76,7 +77,7 @@
     private static final String DEFAULT_MCAST_ADDR = "224.0.0.0/4";
 
     @Property(name = "multicastAddress",
-            label = "Define the multicast base raneg to listen to")
+            label = "Define the multicast base range to listen to")
     private String multicastAddress = DEFAULT_MCAST_ADDR;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -194,6 +195,7 @@
     }
 
     private void processQuery(IGMP pkt, ConnectPoint location) {
+        // TODO is this the right thing to do for a query?
         pkt.getGroups().forEach(group -> group.getSources().forEach(src -> {
 
             McastRoute route = new McastRoute(src,
@@ -205,6 +207,36 @@
         }));
     }
 
+    private void processMembership(IGMP pkt, ConnectPoint location) {
+        pkt.getGroups().forEach(group -> {
+
+            if (!(group instanceof IGMPMembership)) {
+                log.warn("Wrong group type in IGMP membership");
+                return;
+            }
+
+            IGMPMembership membership = (IGMPMembership) group;
+
+            McastRoute route = new McastRoute(IpAddress.valueOf("0.0.0.0"),
+                    group.getGaddr(),
+                    McastRoute.Type.IGMP);
+
+            if (membership.getRecordType() == IGMPMembership.MODE_IS_INCLUDE ||
+                    membership.getRecordType() == IGMPMembership.CHANGE_TO_INCLUDE_MODE) {
+
+
+                multicastService.add(route);
+                multicastService.addSink(route, location);
+
+            } else if (membership.getRecordType() == IGMPMembership.MODE_IS_EXCLUDE ||
+                    membership.getRecordType() == IGMPMembership.CHANGE_TO_EXCLUDE_MODE) {
+                multicastService.removeSink(route, location);
+                // TODO remove route if all sinks are gone
+            }
+
+        });
+    }
+
     /**
      * Packet processor responsible for handling IGMP packets.
      */
@@ -259,7 +291,7 @@
             switch (igmp.getIgmpType()) {
 
                 case IGMP.TYPE_IGMPV3_MEMBERSHIP_REPORT:
-                    IGMPProcessMembership.processMembership(igmp, pkt.receivedFrom());
+                    processMembership(igmp, pkt.receivedFrom());
                     break;
 
                 case IGMP.TYPE_IGMPV3_MEMBERSHIP_QUERY:
@@ -269,12 +301,11 @@
                 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: " +
+                    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());
+                    log.debug("Unknown IGMP message type: {}", igmp.getIgmpType());
                     break;
             }
         }
@@ -312,7 +343,6 @@
                     log.warn("Unknown device event {}", event.type());
                     break;
             }
-
         }
 
         @Override
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/mcast/impl/DistributedMcastStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/mcast/impl/DistributedMcastStore.java
index 5af5266..331ecbb 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/mcast/impl/DistributedMcastStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/mcast/impl/DistributedMcastStore.java
@@ -54,13 +54,11 @@
         mcastRib = storageService.<McastRoute, MulticastData>consistentMapBuilder()
                 .withName(MCASTRIB)
                 .withSerializer(Serializer.using(KryoNamespace.newBuilder()
-                        .register(KryoNamespaces.BASIC)
-                        .register(KryoNamespaces.MISC)
+                        .register(KryoNamespaces.API)
                         .register(
                         MulticastData.class,
                         McastRoute.class,
-                        McastRoute.Type.class,
-                        ConnectPoint.class
+                        McastRoute.Type.class
                 ).build()))
                 //.withRelaxedReadConsistency()
                 .build();
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/mcast/impl/MulticastData.java b/incubator/store/src/main/java/org/onosproject/incubator/store/mcast/impl/MulticastData.java
index 75b5206..11741b5 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/mcast/impl/MulticastData.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/mcast/impl/MulticastData.java
@@ -16,9 +16,9 @@
 package org.onosproject.incubator.store.mcast.impl;
 
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
 import org.onosproject.net.ConnectPoint;
 
+import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
@@ -37,13 +37,16 @@
     private final AtomicBoolean isEmpty = new AtomicBoolean();
 
     private MulticastData() {
-        this.sinks = Sets.newConcurrentHashSet();
+        // FIXME we have major problems trying to serialize these sets
+        //this.sinks = Sets.newConcurrentHashSet();
+        this.sinks = new HashSet<>();
         isEmpty.set(true);
     }
 
     public MulticastData(ConnectPoint source) {
         this.source.set(checkNotNull(source, "Multicast source cannot be null."));
-        this.sinks = Sets.newConcurrentHashSet();
+        //this.sinks = Sets.newConcurrentHashSet();
+        this.sinks = new HashSet<>();
         isEmpty.set(false);
     }
 
diff --git a/utils/misc/src/main/java/org/onlab/packet/IGMPMembership.java b/utils/misc/src/main/java/org/onlab/packet/IGMPMembership.java
index 495e283..d5eb2d8 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IGMPMembership.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IGMPMembership.java
@@ -20,6 +20,7 @@
 
 public class IGMPMembership extends IGMPGroup {
 
+    // TODO should be an enum
     public static final byte MODE_IS_INCLUDE = 0x1;
     public static final byte MODE_IS_EXCLUDE = 0x2;
     public static final byte CHANGE_TO_INCLUDE_MODE = 0x3;
@@ -50,6 +51,15 @@
     }
 
     /**
+     * Gets the IGMP record type.
+     *
+     * @return record type
+     */
+    public byte getRecordType() {
+        return recordType;
+    }
+
+    /**
      * Serialize this Membership Report.
      *
      * @param bb the ByteBuffer to write into, positioned at the next spot to be written to.