[AETHER-537][AETHER-1031][AETHER-540] Several bugfixes for SR (p2)

This patch includes:
- new method to update the indirect nexthops when the
  internal vlan is changed
- fix update l2 interface scenario (tagged <-> untagged)
- fix a race condition during the removal of fwd objectives
- new method to signal the driver when a port update is happening
- minor fixes in the log messages
- fix two issues in the update of the l3 unicast. One is related
  to the vlan to be used during the nexthop moves. Another issue
  was happening when there was a mismatch between hostVlan and
  vlan configuration on a specific port

Change-Id: I149a03c09daafc015ea4bf131b0968761d02273c
diff --git a/impl/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/impl/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 9c3b713..76ca8b7 100644
--- a/impl/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/impl/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -38,6 +38,7 @@
 import org.onosproject.net.flowobjective.DefaultObjectiveContext;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
 import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
 import org.onosproject.net.flowobjective.ObjectiveContext;
 import org.onosproject.net.link.LinkService;
 import org.onosproject.segmentrouting.DefaultRoutingHandler;
@@ -60,6 +61,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -1475,12 +1477,14 @@
      * @param portNum  the outgoing port on the device
      * @param treatment the actions applied on the packets (should include outport)
      * @param meta optional data to pass to the driver
+     * @return a completable future that completes when the port has been removed
      */
-    public void removeGroupFromPort(PortNumber portNum, TrafficTreatment treatment,
-                                    TrafficSelector meta) {
+    public CompletableFuture<Objective> removeGroupFromPort(PortNumber portNum, TrafficTreatment treatment,
+                                                            TrafficSelector meta) {
         PortNextObjectiveStoreKey key = new PortNextObjectiveStoreKey(
                 deviceId, portNum, treatment, meta);
         Integer nextId = portNextObjStore.get(key);
+        CompletableFuture<Objective> future = new CompletableFuture<>();
 
         NextObjective.Builder nextObjBuilder = DefaultNextObjective
                 .builder().withId(nextId)
@@ -1490,12 +1494,14 @@
                 .withMeta(meta);
 
         ObjectiveContext context = new DefaultObjectiveContext(
-                (objective) ->
-                        log.info("removeGroupFromPort installed "
-                                          + "NextObj {} on {}", nextId, deviceId),
+                (objective) -> {
+                    log.info("removeGroupFromPort done " + "NextObj {} on {}", nextId, deviceId);
+                    future.complete(objective);
+                },
                 (objective, error) -> {
                     log.warn("removeGroupFromPort failed to install NextObj {} on {}: {}", nextId, deviceId, error);
                     srManager.invalidateNextObj(objective.id());
+                    future.complete(null);
                 }
         );
         NextObjective nextObj = nextObjBuilder.remove(context);
@@ -1504,6 +1510,7 @@
                           + "for port {}", nextId, deviceId, portNum);
 
         portNextObjStore.remove(key);
+        return future;
     }
 
     /**
@@ -1627,6 +1634,10 @@
                         hostMac, hostVlanId, connectPoint);
                 return;
             }
+        } else {
+            log.warn("Tagged nexthop {}/{} is not allowed on {} without VLAN listed"
+                    + " in tagged vlan", hostMac, hostVlanId, connectPoint);
+            return;
         }
 
         log.debug(" update L3Ucast : deviceMac {}, port {}, host {}/{}, nextid {}, Treatment {} Meta {}",