fixing igmp bootstrap issues

Change-Id: Id8d7b6c33fa4196db72ea049b484cb9c52d2c87f
diff --git a/features.xml b/features.xml
new file mode 100644
index 0000000..2c4aa1b
--- /dev/null
+++ b/features.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ Copyright 2016 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.
+  -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+    <feature name="onos-app-igmp" version="${project.version}"
+             description="${project.description}">
+        <feature>onos-api</feature>
+        <bundle>mvn:${project.groupId}/onos-app-olt-api/${project.version}</bundle>
+        <bundle>mvn:${project.groupId}/onos-app-igmp/${project.version}</bundle>
+    </feature>
+</features>
diff --git a/src/main/java/org/onosproject/igmp/IgmpSnoop.java b/src/main/java/org/onosproject/igmp/IgmpSnoop.java
index c0af0bf..3ade419 100644
--- a/src/main/java/org/onosproject/igmp/IgmpSnoop.java
+++ b/src/main/java/org/onosproject/igmp/IgmpSnoop.java
@@ -34,7 +34,11 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
 import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.basics.SubjectFactories;
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
@@ -56,6 +60,7 @@
 import org.onosproject.olt.AccessDeviceData;
 import org.slf4j.Logger;
 
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -98,12 +103,31 @@
     private IgmpPacketProcessor processor = new IgmpPacketProcessor();
     private static ApplicationId appId;
 
+    private InternalNetworkConfigListener configListener =
+            new InternalNetworkConfigListener();
+
+    private static final Class<AccessDeviceConfig> CONFIG_CLASS =
+            AccessDeviceConfig.class;
+
+    private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
+            new ConfigFactory<DeviceId, AccessDeviceConfig>(
+                    SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
+                @Override
+                public AccessDeviceConfig createConfig() {
+                    return new AccessDeviceConfig();
+                }
+            };
+
+
     @Activate
     public void activate() {
         appId = coreService.registerApplication("org.onosproject.igmp");
 
         packetService.addProcessor(processor, PacketProcessor.director(1));
 
+        networkConfig.registerConfigFactory(configFactory);
+        networkConfig.addListener(configListener);
+
         networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
                 subject -> {
                     AccessDeviceConfig config = networkConfig.getConfig(subject,
@@ -111,10 +135,17 @@
                     if (config != null) {
                         AccessDeviceData data = config.getOlt();
                         oltData.put(data.deviceId(), data);
+
                     }
                 }
         );
 
+        oltData.keySet().stream()
+                .flatMap(did -> deviceService.getPorts(did).stream())
+                .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
+                .filter(p -> p.isEnabled())
+                .forEach(p -> processFilterObjective((DeviceId) p.element().id(), p, false));
+
         deviceService.addListener(deviceListener);
 
         log.info("Started");
@@ -125,6 +156,8 @@
         packetService.removeProcessor(processor);
         processor = null;
         deviceService.removeListener(deviceListener);
+        networkConfig.removeListener(configListener);
+        networkConfig.unregisterConfigFactory(configFactory);
         log.info("Stopped");
     }
 
@@ -248,7 +281,6 @@
     }
 
 
-
     private class InternalDeviceListener implements DeviceListener {
         @Override
         public void event(DeviceEvent event) {
@@ -274,7 +306,7 @@
                     }
                     break;
                 case PORT_REMOVED:
-                    processFilterObjective(event.subject().id(), event.port(), false);
+                    processFilterObjective(event.subject().id(), event.port(), true);
                     break;
                 default:
                     log.warn("Unknown device event {}", event.type());
@@ -288,4 +320,38 @@
             return oltData.containsKey(event.subject().id());
         }
     }
+
+    private class InternalNetworkConfigListener implements NetworkConfigListener {
+        @Override
+        public void event(NetworkConfigEvent event) {
+            switch (event.type()) {
+
+                case CONFIG_ADDED:
+                case CONFIG_UPDATED:
+                    if (event.configClass().equals(CONFIG_CLASS)) {
+                        AccessDeviceConfig config =
+                                networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
+                        if (config != null) {
+                            oltData.put(config.getOlt().deviceId(), config.getOlt());
+                            provisionDefaultFlows((DeviceId) event.subject());
+                        }
+                    }
+                    break;
+                case CONFIG_UNREGISTERED:
+                case CONFIG_REMOVED:
+                default:
+                    break;
+            }
+        }
+    }
+
+    private void provisionDefaultFlows(DeviceId deviceId) {
+        List<Port> ports = deviceService.getPorts(deviceId);
+
+        ports.stream()
+                .filter(p -> !oltData.get(p.element().id()).uplink().equals(p.number()))
+                .filter(p -> p.isEnabled())
+                .forEach(p -> processFilterObjective((DeviceId) p.element().id(), p, false));
+
+    }
 }