Calculate IGMP checksum and use more reasonble max response time.

Also made IGMP properties configurable at runtime.

Change-Id: I98b40a43a0c17b7bf21f1bd622032c64d7434214
diff --git a/src/main/java/org/onosproject/igmp/IgmpSnoop.java b/src/main/java/org/onosproject/igmp/IgmpSnoop.java
index 03f561b..19bd221 100644
--- a/src/main/java/org/onosproject/igmp/IgmpSnoop.java
+++ b/src/main/java/org/onosproject/igmp/IgmpSnoop.java
@@ -18,6 +18,7 @@
 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.Modified;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
@@ -31,6 +32,8 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.util.SafeRecurringTask;
+import org.onlab.util.Tools;
+import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.net.ConnectPoint;
@@ -63,12 +66,15 @@
 import org.onosproject.net.packet.PacketService;
 import org.onosproject.olt.AccessDeviceConfig;
 import org.onosproject.olt.AccessDeviceData;
+import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 
 import java.nio.ByteBuffer;
 import java.util.Collection;
+import java.util.Dictionary;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
@@ -90,7 +96,7 @@
     private static final String DEST_IP = "224.0.0.1";
 
     private static final int DEFAULT_QUERY_PERIOD_SECS = 60;
-    private static final byte DEFAULT_IGMP_RESP_CODE = 0;
+    private static final byte DEFAULT_IGMP_RESP_CODE = 100;
     private static final String DEFAULT_MCAST_ADDR = "224.0.0.0/4";
 
     @Property(name = "multicastAddress",
@@ -118,6 +124,9 @@
     protected NetworkConfigRegistry networkConfig;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected ComponentConfigService componentConfigService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected MulticastRouteService multicastService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -169,9 +178,13 @@
 
 
     @Activate
-    public void activate() {
+    public void activate(ComponentContext context) {
+        modified(context);
+
         appId = coreService.registerApplication("org.onosproject.igmp");
 
+        componentConfigService.registerProperties(getClass());
+
         packetService.addProcessor(processor, PacketProcessor.director(1));
 
         networkConfig.registerConfigFactory(configFactory);
@@ -208,13 +221,7 @@
 
         deviceService.addListener(deviceListener);
 
-        queryPacket = buildQueryPacket();
-
-        queryTask = queryService.scheduleWithFixedDelay(
-                SafeRecurringTask.wrap(this::querySubscribers),
-                0,
-                queryPeriod,
-                TimeUnit.SECONDS);
+        restartQueryTask();
 
         log.info("Started");
     }
@@ -229,9 +236,49 @@
         networkConfig.unregisterConfigFactory(ssmTranslateConfigFactory);
         queryTask.cancel(true);
         queryService.shutdownNow();
+        componentConfigService.unregisterProperties(getClass(), false);
         log.info("Stopped");
     }
 
+    @Modified
+    protected void modified(ComponentContext context) {
+        Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
+
+        String strQueryPeriod = Tools.get(properties, "queryPeriod");
+        String strResponseCode = Tools.get(properties, "maxRespCode");
+        try {
+            byte newMaxRespCode = Byte.parseByte(strResponseCode);
+            if (maxRespCode != newMaxRespCode) {
+                maxRespCode = newMaxRespCode;
+                queryPacket = buildQueryPacket();
+            }
+
+            int newQueryPeriod = Integer.parseInt(strQueryPeriod);
+            if (newQueryPeriod != queryPeriod) {
+                queryPeriod = newQueryPeriod;
+                restartQueryTask();
+            }
+
+        } catch (NumberFormatException e) {
+            log.warn("Error parsing config input", e);
+        }
+
+        log.info("queryPeriod set to {}", queryPeriod);
+        log.info("maxRespCode set to {}", maxRespCode);
+    }
+
+    private void restartQueryTask() {
+        if (queryTask != null) {
+            queryTask.cancel(true);
+        }
+        queryPacket = buildQueryPacket();
+        queryTask = queryService.scheduleWithFixedDelay(
+                SafeRecurringTask.wrap(this::querySubscribers),
+                0,
+                queryPeriod,
+                TimeUnit.SECONDS);
+    }
+
     private void processFilterObjective(DeviceId devId, Port port, boolean remove) {
 
         //TODO migrate to packet requests when packet service uses filtering objectives