CORD-999 changes to support vlans
Major changes to the DhcpRelay app
   Bug fix to not depend on global variables that can be overwritten
   App is now vlan aware i.e. client and server can be in different vlans
   Added probing of dhcpServer to get mac/vlan instead of configuring these values
   Added optional gateway IP for cases where dhcpServer is "behind" external router
Added support in host monitor for trunk vlan configurations
Javadoc fix in Interface.java
Commented out unused log message in HostLocationProvider
Bug fix to make ALL group editing vlan aware.

Change-Id: Ib04ed6c1ef45055f771983db29724cfde24ac54b
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index dc3f358..0a3eb92 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -1015,30 +1015,41 @@
         // to switch ports, link-events should take care of any re-routing or
         // group editing necessary for port up/down. Here we only process edge ports
         // that are already configured.
-        VlanId untaggedVlan = getUntaggedVlanId(new ConnectPoint(device.id(), port.number()));
-        VlanId vlanId = (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
+        ConnectPoint cp = new ConnectPoint(device.id(), port.number());
+        VlanId untaggedVlan = getUntaggedVlanId(cp);
+        VlanId nativeVlan = getNativeVlanId(cp);
+        Set<VlanId> taggedVlans = getTaggedVlanId(cp);
 
-        if (vlanId.equals(INTERNAL_VLAN)) {
+        if (untaggedVlan == null && nativeVlan == null && taggedVlans.isEmpty()) {
             log.debug("Not handling port updated event for unconfigured port "
                     + "dev/port: {}/{}", device.id(), port.number());
             return;
         }
-        processEdgePort(device, port, vlanId);
+        if (untaggedVlan != null) {
+            processEdgePort(device, port, untaggedVlan, true);
+        }
+        if (nativeVlan != null) {
+            processEdgePort(device, port, nativeVlan, true);
+        }
+        if (!taggedVlans.isEmpty()) {
+            taggedVlans.forEach(tag -> processEdgePort(device, port, tag, false));
+        }
     }
 
-    private void processEdgePort(Device device, Port port, VlanId vlanId) {
+    private void processEdgePort(Device device, Port port, VlanId vlanId,
+                                 boolean popVlan) {
         boolean portUp = port.isEnabled();
         if (portUp) {
-            log.info("Device:EdgePort {}:{} is enabled in subnet: {}", device.id(),
+            log.info("Device:EdgePort {}:{} is enabled in vlan: {}", device.id(),
                      port.number(), vlanId);
         } else {
-            log.info("Device:EdgePort {}:{} is disabled in subnet: {}", device.id(),
+            log.info("Device:EdgePort {}:{} is disabled in vlan: {}", device.id(),
                      port.number(), vlanId);
         }
 
         DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
         if (groupHandler != null) {
-            groupHandler.processEdgePort(port.number(), vlanId, portUp);
+            groupHandler.processEdgePort(port.number(), vlanId, popVlan, portUp);
         } else {
             log.warn("Group handler not found for dev:{}. Not handling edge port"
                     + " {} event for port:{}", device.id(),
diff --git a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 9e7fd04..93dfd0c 100644
--- a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -360,15 +360,18 @@
     }
 
     /**
-     * Adds or removes a port that has been configured with a subnet to a broadcast group
-     * for bridging. Note that this does not create the broadcast group itself.
-     * Should only be called by the master instance for this device/port.
+     * Adds or removes a port that has been configured with a vlan to a broadcast group
+     * for bridging. Should only be called by the master instance for this device.
      *
      * @param port the port on this device that needs to be added/removed to a bcast group
-     * @param vlanId the vlan id corresponding to the broadcast group
+     * @param vlanId the vlan id corresponding to the broadcast domain/group
+     * @param popVlan indicates if packets should be sent out untagged or not out
+     *                of the port. If true, indicates an access (untagged) or native vlan
+     *                configuration. If false, indicates a trunk (tagged) vlan config.
      * @param portUp true if port is enabled, false if disabled
      */
-    public void processEdgePort(PortNumber port, VlanId vlanId, boolean portUp) {
+    public void processEdgePort(PortNumber port, VlanId vlanId,
+                                boolean popVlan, boolean portUp) {
         //get the next id for the subnet and edit it.
         Integer nextId = getVlanNextObjectiveId(vlanId);
         if (nextId == -1) {
@@ -389,14 +392,13 @@
                                           port, nextId);
         // Create the bucket to be added or removed
         TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-        tBuilder.popVlan();
+        if (popVlan) {
+            tBuilder.popVlan();
+        }
         tBuilder.setOutput(port);
 
-        VlanId untaggedVlan = srManager.getUntaggedVlanId(new ConnectPoint(deviceId, port));
-        VlanId assignedVlanId = (untaggedVlan != null) ? untaggedVlan : INTERNAL_VLAN;
-
         TrafficSelector metadata =
-                DefaultTrafficSelector.builder().matchVlanId(assignedVlanId).build();
+                DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
 
         NextObjective.Builder nextObjBuilder = DefaultNextObjective
                 .builder().withId(nextId)