ONOS-2742: Register entire VLAN ID space when a link is discovered

Change-Id: Ia00a1e732e3cf458a899baa25307de813cca4aef
diff --git a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java
index bdd2f67..c87ca29 100644
--- a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java
+++ b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceLinkListener.java
@@ -15,14 +15,23 @@
  */
 package org.onosproject.net.newresource.impl;
 
+import org.onlab.packet.VlanId;
+import org.onlab.util.ItemNotFoundException;
+import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Link;
 import org.onosproject.net.LinkKey;
+import org.onosproject.net.behaviour.VlanQuery;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.link.LinkEvent;
 import org.onosproject.net.link.LinkListener;
 import org.onosproject.net.newresource.ResourceAdminService;
 import org.onosproject.net.newresource.ResourcePath;
 
+import java.util.List;
 import java.util.concurrent.ExecutorService;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
@@ -31,7 +40,11 @@
  */
 final class ResourceLinkListener implements LinkListener {
 
+    private static final int TOTAL_VLANS = 1024;
+    private static final List<VlanId> ENTIRE_VLAN_IDS = getEntireVlans();
+
     private final ResourceAdminService adminService;
+    private final DriverService driverService;
     private final ExecutorService executor;
 
     /**
@@ -40,8 +53,9 @@
      * @param adminService instance invoked to register resources
      * @param executor executor used for processing resource registration
      */
-    ResourceLinkListener(ResourceAdminService adminService, ExecutorService executor) {
+    ResourceLinkListener(ResourceAdminService adminService, DriverService driverService, ExecutorService executor) {
         this.adminService = checkNotNull(adminService);
+        this.driverService = checkNotNull(driverService);
         this.executor = checkNotNull(executor);
     }
 
@@ -61,12 +75,47 @@
     }
 
     private void registerLinkResource(Link link) {
-        LinkKey linkKey = LinkKey.linkKey(link);
-        executor.submit(() -> adminService.registerResources(ResourcePath.ROOT, linkKey));
+        executor.submit(() -> {
+            // register the link
+            LinkKey linkKey = LinkKey.linkKey(link);
+            adminService.registerResources(ResourcePath.ROOT, linkKey);
+
+            // register VLAN IDs against the link
+            if (isVlanEnabled(link)) {
+                adminService.registerResources(new ResourcePath(linkKey), ENTIRE_VLAN_IDS);
+            }
+        });
     }
 
     private void unregisterLinkResource(Link link) {
         LinkKey linkKey = LinkKey.linkKey(link);
         executor.submit(() -> adminService.unregisterResources(ResourcePath.ROOT, linkKey));
     }
+
+    private boolean isVlanEnabled(Link link) {
+        ConnectPoint src = link.src();
+        ConnectPoint dst = link.dst();
+
+        return isVlanEnabled(src) && isVlanEnabled(dst);
+    }
+
+    private boolean isVlanEnabled(ConnectPoint cp) {
+        try {
+            DriverHandler handler = driverService.createHandler(cp.deviceId());
+            if (handler == null) {
+                return false;
+            }
+
+            VlanQuery query = handler.behaviour(VlanQuery.class);
+            return query != null && query.isEnabled(cp.port());
+        } catch (ItemNotFoundException e) {
+            return false;
+        }
+    }
+
+    private static List<VlanId> getEntireVlans() {
+        return IntStream.range(0, TOTAL_VLANS)
+                .mapToObj(x -> VlanId.vlanId((short) x))
+                .collect(Collectors.toList());
+    }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java
index 6294892..4067d01 100644
--- a/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java
+++ b/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceRegistrar.java
@@ -23,6 +23,7 @@
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.link.LinkListener;
 import org.onosproject.net.link.LinkService;
 import org.onosproject.net.newresource.ResourceAdminService;
@@ -43,6 +44,9 @@
     protected ResourceAdminService adminService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DriverService driverService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -57,7 +61,7 @@
     public void activate() {
         deviceListener = new ResourceDeviceListener(adminService, executor);
         deviceService.addListener(deviceListener);
-        linkListener = new ResourceLinkListener(adminService, executor);
+        linkListener = new ResourceLinkListener(adminService, driverService, executor);
         linkService.addListener(linkListener);
     }