CORD-906 Support trunk and native VLAN

- Include trunk L2IG in L2F
- Populate bridging rules for trunk vlan
- Extend populateVlanMacFilters to generate filtering obj for trunk port
- Extend host handler to check vlan mismatch between host and interface
  (Temporarily disabled for now. Check TODOs in the code for detail.)
- Extend getForwardingObjectiveBuilder in RoutingRulePopulator to support tagged host

Change-Id: Id168a02015f58b0957ba43ad7c52798029d895bc
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 2b1a8c2..9e7fd04 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -49,6 +49,7 @@
 
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -737,20 +738,8 @@
      */
     public void createGroupsFromVlanConfig() {
         Set<Interface> interfaces = srManager.interfaceService.getInterfaces();
-        Set<VlanId> vlans =
-        interfaces.stream()
-                .filter(intf -> intf.connectPoint().deviceId().equals(deviceId) &&
-                        !intf.vlanUntagged().equals(VlanId.NONE))
-                .map(Interface::vlanUntagged)
-                .collect(Collectors.toSet());
 
-        vlans.forEach(vlanId -> {
-            Set<PortNumber> ports = interfaces.stream()
-                    .filter(intf -> intf.connectPoint().deviceId().equals(deviceId) &&
-                            intf.vlanUntagged().equals(vlanId))
-                    .map(Interface::connectPoint)
-                    .map(ConnectPoint::port)
-                    .collect(Collectors.toSet());
+        srManager.getVlanPortMap(deviceId).asMap().forEach((vlanId, ports) -> {
             createBcastGroupFromVlan(vlanId, ports);
         });
     }
@@ -761,7 +750,7 @@
      * @param vlanId vlan id
      * @param ports list of ports in the subnet
      */
-    public void createBcastGroupFromVlan(VlanId vlanId, Set<PortNumber> ports) {
+    public void createBcastGroupFromVlan(VlanId vlanId, Collection<PortNumber> ports) {
         VlanNextObjectiveStoreKey key = new VlanNextObjectiveStoreKey(deviceId, vlanId);
 
         if (vlanNextObjStore.containsKey(key)) {
@@ -782,7 +771,9 @@
 
         ports.forEach(port -> {
             TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-            tBuilder.popVlan();
+            if (toPopVlan(port, vlanId)) {
+                tBuilder.popVlan();
+            }
             tBuilder.setOutput(port);
             nextObjBuilder.addTreatment(tBuilder.build());
         });
@@ -796,6 +787,18 @@
     }
 
     /**
+     * Determine if we should pop given vlan before sending packets to the given port.
+     *
+     * @param portNumber port number
+     * @param vlanId vlan id
+     * @return true if the vlan id is not contained in any vlanTagged config
+     */
+    private boolean toPopVlan(PortNumber portNumber, VlanId vlanId) {
+        return srManager.interfaceService.getInterfacesByPort(new ConnectPoint(deviceId, portNumber))
+                .stream().noneMatch(intf -> intf.vlanTagged().contains(vlanId));
+    }
+
+    /**
      * Create simple next objective for a single port. The treatments can include
      * all outgoing actions that need to happen on the packet.
      *