AETHER-1485 Prevent routerMac from being learnt

Change-Id: I2d8f038c228b4c865c4835fe10be044aa5aa6323
diff --git a/impl/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java b/impl/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
index 04d63a2..0f9efce 100644
--- a/impl/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
+++ b/impl/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
@@ -16,6 +16,7 @@
 package org.onosproject.segmentrouting;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.google.common.collect.HashMultimap;
@@ -36,6 +37,7 @@
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.config.ConfigException;
 import org.onosproject.net.config.basics.BasicDeviceConfig;
+import org.onosproject.net.config.basics.BasicHostConfig;
 import org.onosproject.net.config.basics.InterfaceConfig;
 import org.onosproject.net.host.InterfaceIpAddress;
 import org.onosproject.net.intf.Interface;
@@ -70,6 +72,8 @@
 public class DeviceConfiguration implements DeviceProperties {
 
     private static final String NO_SUBNET = "No subnet configured on {}";
+    // Key for BasicHostConfig
+    private static final String BASIC_KEY = "basic";
 
     private static final Logger log = LoggerFactory.getLogger(DeviceConfiguration.class);
     private final List<Integer> allSegmentIds = new ArrayList<>();
@@ -137,10 +141,11 @@
             info.pwRoutingLabel = info.ipv4NodeSid + 1000;
             deviceConfigMap.put(info.deviceId, info);
             log.debug("Read device config for device: {}", info.deviceId);
-            /*
-             * IPv6 sid is not inserted. this part of the code is not used for now.
-             */
+            // IPv6 sid is not inserted. this part of the code is not used for now.
             allSegmentIds.add(info.ipv4NodeSid);
+
+            // Block host with routerMac and untagged VLAN
+            blockHost(info.mac, VlanId.NONE);
         });
 
         // Read gatewayIps and subnets from port subject. Ignore suppressed ports.
@@ -166,7 +171,7 @@
                 MacAddress mac = networkInterface.mac();
                 SegmentRouterInfo info = deviceConfigMap.get(dpid);
 
-                // skip if there is no corresponding device for this ConenctPoint
+                // skip if there is no corresponding device for this ConnectPoint
                 if (info != null) {
                     // Extract subnet information
                     List<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddressesList();
@@ -196,6 +201,11 @@
                         }
                         srManager.cfgService.applyConfig(connectPoint, InterfaceConfig.class, array);
                     }
+
+                    // Block host with routerMac and taggedVlan
+                    networkInterface.vlanTagged().forEach(taggedVlan -> {
+                        blockHost(info.mac, taggedVlan);
+                    });
                 }
             });
             // We register the connect point with the NRS.
@@ -203,6 +213,20 @@
         });
     }
 
+    private void blockHost(MacAddress macAddress, VlanId vlanId) {
+        HostId hostId = HostId.hostId(macAddress, vlanId);
+        BasicHostConfig hostConfig = srManager.cfgService.getConfig(hostId, BasicHostConfig.class);
+        if (hostConfig == null) {
+            ObjectMapper mapper = new ObjectMapper();
+            JsonNode jsonNode = mapper.createObjectNode();
+            hostConfig = new BasicHostConfig();
+            hostConfig.init(hostId, BASIC_KEY, jsonNode, mapper, config -> { });
+        }
+        hostConfig.isAllowed(false);
+        srManager.cfgService.applyConfig(hostId, BasicHostConfig.class, hostConfig.node());
+        log.info("Blocking {} from being learnt as host", hostId);
+    }
+
     public Collection<DeviceId> getRouters() {
         return deviceConfigMap.keySet();
     }
diff --git a/impl/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java b/impl/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java
index d482d60..5bb40f3 100644
--- a/impl/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java
+++ b/impl/src/test/java/org/onosproject/segmentrouting/config/DeviceConfigurationTest.java
@@ -28,9 +28,11 @@
 import org.onlab.packet.VlanId;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.config.NetworkConfigRegistry;
 import org.onosproject.net.config.basics.BasicDeviceConfig;
+import org.onosproject.net.config.basics.BasicHostConfig;
 import org.onosproject.net.config.basics.InterfaceConfig;
 import org.onosproject.net.host.InterfaceIpAddress;
 import org.onosproject.net.intf.Interface;
@@ -59,6 +61,8 @@
     private static final ConnectPoint CP1 = new ConnectPoint(DEV1, PORT1);
     private static final ConnectPoint CP2 = new ConnectPoint(DEV1, PORT2);
     private static final MacAddress MAC1 = MacAddress.valueOf("00:11:22:33:44:55");
+    private static final MacAddress ROUTER_MAC = MacAddress.valueOf("00:00:00:00:01:80");
+    private static final HostId ROUTER_HOST = HostId.hostId(ROUTER_MAC, VlanId.NONE);
     private static final VlanId VLAN1 = VlanId.vlanId((short) 10);
     private static final VlanId VLAN2 = VlanId.vlanId((short) 20);
     private static final IpPrefix PREFIX1 = IpPrefix.valueOf("10.0.1.254/24");
@@ -101,11 +105,17 @@
         jsonNode = mapper.readTree(jsonStream);
         InterfaceConfig interfaceConfig1 = new InterfaceConfig();
         interfaceConfig1.init(CP1, CONFIG_KEY, jsonNode, mapper, config -> { });
+
         jsonStream = InterfaceConfig.class.getResourceAsStream("/interface2.json");
         jsonNode = mapper.readTree(jsonStream);
         InterfaceConfig interfaceConfig2 = new InterfaceConfig();
         interfaceConfig2.init(CP1, CONFIG_KEY, jsonNode, mapper, config -> { });
 
+        jsonStream = BasicHostConfig.class.getResourceAsStream("/host1.json");
+        jsonNode = mapper.readTree(jsonStream);
+        BasicHostConfig hostConfig1 = new BasicHostConfig();
+        hostConfig1.init(ROUTER_HOST, "basic", jsonNode, mapper, config -> { });
+
         networkConfigService = createMock(NetworkConfigRegistry.class);
         expect(networkConfigService.getSubjects(DeviceId.class, SegmentRoutingDeviceConfig.class))
                 .andReturn(Sets.newHashSet(DEV1)).anyTimes();
@@ -126,6 +136,9 @@
         expect(networkConfigService.applyConfig(eq(CP2), eq(InterfaceConfig.class), anyObject()))
                 .andReturn(interfaceConfig2).anyTimes();
         expect(networkConfigService.getConfig(null, SegmentRoutingAppConfig.class)).andReturn(null).anyTimes();
+        expect(networkConfigService.getConfig(ROUTER_HOST, BasicHostConfig.class)).andReturn(hostConfig1).anyTimes();
+        expect(networkConfigService.applyConfig(eq(ROUTER_HOST), eq(BasicHostConfig.class), anyObject()))
+                .andReturn(hostConfig1).anyTimes();
         replay(networkConfigService);
 
         interfaceService = createMock(InterfaceService.class);
diff --git a/impl/src/test/resources/host1.json b/impl/src/test/resources/host1.json
new file mode 100644
index 0000000..9df4c72
--- /dev/null
+++ b/impl/src/test/resources/host1.json
@@ -0,0 +1,3 @@
+{
+  "allowed": false
+}
\ No newline at end of file