Implement component config to enable double tagged host programming

Change-Id: I4b2c113e5ddcfe23f825fb15d053cc2ee48ee9e1
diff --git a/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index d4fbcad..e4d85de 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -529,6 +529,11 @@
                                                 MacAddress mac, VlanId innerVlan,
                                                 VlanId outerVlan, EthType outerTpid,
                                                 IpAddress ip, boolean revoke) {
+        if (!srManager.handleDoubleTaggedHosts) {
+            log.debug("Ignore double tagged host {}/{}/{}", mac, outerVlan, innerVlan);
+            return;
+        }
+
         ConnectPoint location = new ConnectPoint(deviceId, port);
         if (!srManager.deviceConfiguration.inSameSubnet(location, ip)) {
             log.info("{} is not included in the subnet config of {}/{}. Ignored.", ip, deviceId, port);
@@ -545,6 +550,30 @@
         }
     }
 
+    void populateAllDoubleTaggedHost() {
+        log.info("Populating all double tagged hosts");
+        Sets.newHashSet(srManager.hostService.getHosts()).stream().filter(this::isDoubleTaggedHost)
+                .forEach(h -> h.locations().forEach(l ->
+                    h.ipAddresses().forEach(i ->
+                        processDoubleTaggedRoutingRule(l.deviceId(), l.port(), h.mac(), h.innerVlan(),
+                                h.vlan(), h.tpid(), i, false)
+                    )
+            )
+        );
+    }
+
+    void revokeAllDoubleTaggedHost() {
+        log.info("Revoking all double tagged hosts");
+        Sets.newHashSet(srManager.hostService.getHosts()).stream().filter(this::isDoubleTaggedHost)
+                .forEach(h -> h.locations().forEach(l ->
+                    h.ipAddresses().forEach(i ->
+                        processDoubleTaggedRoutingRule(l.deviceId(), l.port(), h.mac(), h.innerVlan(),
+                            h.vlan(), h.tpid(), i, true)
+                    )
+            )
+        );
+    }
+
     /**
      * Returns VLAN ID to be used to program redirection flow on pair port.
      *
diff --git a/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 292c941..5dc76bc 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -247,6 +247,10 @@
             label = "Enable this to respond to ARP/NDP requests from unknown hosts.")
     boolean respondToUnknownHosts = true;
 
+    @Property(name = "handleDoubleTaggedHosts", boolValue = false,
+            label = "Program flows and groups for double tagged hosts")
+    boolean handleDoubleTaggedHosts = false;
+
     ArpHandler arpHandler = null;
     IcmpHandler icmpHandler = null;
     IpHandler ipHandler = null;
@@ -629,6 +633,19 @@
             respondToUnknownHosts = expectRespondToUnknownHosts;
             log.info("{} responding to ARPs/NDPs from unknown hosts", respondToUnknownHosts ? "Enabling" : "Disabling");
         }
+
+        String strHandleDoubleTaggedHosts = Tools.get(properties, "handleDoubleTaggedHosts");
+        boolean expectHandleDoubleTaggedHosts = Boolean.parseBoolean(strHandleDoubleTaggedHosts);
+        if (expectHandleDoubleTaggedHosts != handleDoubleTaggedHosts) {
+            handleDoubleTaggedHosts = expectHandleDoubleTaggedHosts;
+            log.info("{} programming for double tagged hosts ", handleDoubleTaggedHosts ? "Enabling" : "Disabling");
+
+            if (handleDoubleTaggedHosts) {
+                hostHandler.populateAllDoubleTaggedHost();
+            } else {
+                hostHandler.revokeAllDoubleTaggedHost();
+            }
+        }
     }
 
     @Override