Add INT watchlist config

- add "watchSubnets" to the netcfg of INT app

Change-Id: I271d9c27692c8969999ece32f8aa08b4392216e0
(cherry picked from commit 906febe058507758b67f7074bb1139e3c6170b52)
diff --git a/apps/inbandtelemetry/impl/src/main/java/org/onosproject/inbandtelemetry/impl/SimpleIntManager.java b/apps/inbandtelemetry/impl/src/main/java/org/onosproject/inbandtelemetry/impl/SimpleIntManager.java
index 25d6a50..ffb6b4f 100644
--- a/apps/inbandtelemetry/impl/src/main/java/org/onosproject/inbandtelemetry/impl/SimpleIntManager.java
+++ b/apps/inbandtelemetry/impl/src/main/java/org/onosproject/inbandtelemetry/impl/SimpleIntManager.java
@@ -44,6 +44,8 @@
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.host.HostEvent;
 import org.onosproject.net.host.HostListener;
 import org.onosproject.net.host.HostService;
@@ -591,6 +593,32 @@
                                         .enabled(true)
                                         .build();
                                 setConfig(intDeviceConfig);
+
+                                // For each watched subnet, we install two INT rules.
+                                // One match on the source, another match on the destination.
+                                intentMap.clear();
+                                config.watchSubnets().forEach(subnet -> {
+                                    IntIntent.Builder intIntentBuilder = IntIntent.builder()
+                                            .withReportType(IntIntent.IntReportType.TRACKED_FLOW)
+                                            .withReportType(IntIntent.IntReportType.DROPPED_PACKET)
+                                            .withReportType(IntIntent.IntReportType.CONGESTED_QUEUE)
+                                            .withTelemetryMode(IntIntent.TelemetryMode.POSTCARD);
+                                    if (subnet.prefixLength() == 0) {
+                                        // Special case, match any packet
+                                        installIntIntent(intIntentBuilder
+                                                .withSelector(DefaultTrafficSelector.emptySelector())
+                                                .build());
+                                    } else {
+                                        TrafficSelector selector = DefaultTrafficSelector.builder()
+                                                .matchIPSrc(subnet)
+                                                .build();
+                                        installIntIntent(intIntentBuilder.withSelector(selector).build());
+                                        selector = DefaultTrafficSelector.builder()
+                                                .matchIPDst(subnet)
+                                                .build();
+                                        installIntIntent(intIntentBuilder.withSelector(selector).build());
+                                    }
+                                });
                             });
                     break;
                 // TODO: Support removing INT config.
diff --git a/apps/inbandtelemetry/impl/src/test/java/org/onosproject/inbandtelemetry/impl/SimpleIntManagerTest.java b/apps/inbandtelemetry/impl/src/test/java/org/onosproject/inbandtelemetry/impl/SimpleIntManagerTest.java
index 566ed2b..8519ed5 100644
--- a/apps/inbandtelemetry/impl/src/test/java/org/onosproject/inbandtelemetry/impl/SimpleIntManagerTest.java
+++ b/apps/inbandtelemetry/impl/src/test/java/org/onosproject/inbandtelemetry/impl/SimpleIntManagerTest.java
@@ -27,6 +27,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.onlab.junit.TestUtils;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.TpPort;
@@ -35,6 +36,7 @@
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.inbandtelemetry.api.IntIntent;
+import org.onosproject.inbandtelemetry.api.IntIntentId;
 import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultDevice;
@@ -58,6 +60,7 @@
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.host.HostService;
+import org.onosproject.store.service.ConsistentMap;
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.TestStorageService;
 
@@ -65,6 +68,7 @@
 import java.io.InputStream;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.createNiceMock;
@@ -90,12 +94,14 @@
     private static final int MIN_FLOW_HOP_LATENCY_CHANGE_NS = 32;
     private static final String INT_REPORT_CONFIG_KEY = "report";
     private static final DeviceId DEVICE_ID = DeviceId.deviceId("device:leaf1");
+    private static final String WATCHED_SUBNET_1 = "192.168.10.0/24";
+    private static final String WATCHED_SUBNET_2 = "192.168.20.0/24";
     private static final TrafficSelector FLOW_SELECTOR1 = DefaultTrafficSelector.builder()
-            .matchIPDst(IpPrefix.valueOf("192.168.10.0/24"))
+            .matchIPDst(IpPrefix.valueOf(WATCHED_SUBNET_1))
             .matchVlanId(VlanId.vlanId((short) 10))
             .build();
     private static final TrafficSelector FLOW_SELECTOR2 = DefaultTrafficSelector.builder()
-            .matchIPDst(IpPrefix.valueOf("192.168.20.0/24"))
+            .matchIPDst(IpPrefix.valueOf(WATCHED_SUBNET_2))
             .matchVlanId(VlanId.vlanId((short) 20))
             .build();
     private static final Device DEFAULT_DEVICE =
@@ -182,6 +188,49 @@
         IntDeviceConfig expectedConfig = createIntDeviceConfig();
         IntDeviceConfig actualConfig = manager.getConfig();
         assertEquals(expectedConfig, actualConfig);
+
+        // Install watch subnets via netcfg
+        // In the report-config.json, there are 3 subnets we want to watch
+        // For subnet 0.0.0.0/0, the IntManager will create only one IntIntent with an empty selector.
+        Set<IntIntent> expectedIntIntents = Sets.newHashSet();
+        ConsistentMap<IntIntentId, IntIntent> intentMap = TestUtils.getField(manager, "intentMap");
+        IntIntent.Builder baseIntentBuilder = IntIntent.builder()
+                .withReportType(IntIntent.IntReportType.TRACKED_FLOW)
+                .withReportType(IntIntent.IntReportType.DROPPED_PACKET)
+                .withReportType(IntIntent.IntReportType.CONGESTED_QUEUE)
+                .withTelemetryMode(IntIntent.TelemetryMode.POSTCARD);
+
+        // Watch IP Src == subnet 1
+        TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
+                .matchIPSrc(IpPrefix.valueOf(WATCHED_SUBNET_1))
+                .build();
+        expectedIntIntents.add(baseIntentBuilder.withSelector(expectedSelector).build());
+        // Watch IP Dst == subnet 1
+        expectedSelector = DefaultTrafficSelector.builder()
+                .matchIPDst(IpPrefix.valueOf(WATCHED_SUBNET_1))
+                .build();
+        expectedIntIntents.add(baseIntentBuilder.withSelector(expectedSelector).build());
+        // Watch IP Src == subnet 2
+        expectedSelector = DefaultTrafficSelector.builder()
+                .matchIPSrc(IpPrefix.valueOf(WATCHED_SUBNET_2))
+                .build();
+        expectedIntIntents.add(baseIntentBuilder.withSelector(expectedSelector).build());
+        // Watch IP Dst == subnet 2
+        expectedSelector = DefaultTrafficSelector.builder()
+                .matchIPDst(IpPrefix.valueOf(WATCHED_SUBNET_2))
+                .build();
+        expectedIntIntents.add(baseIntentBuilder.withSelector(expectedSelector).build());
+        // Any packets
+        expectedSelector = DefaultTrafficSelector.emptySelector();
+        expectedIntIntents.add(baseIntentBuilder.withSelector(expectedSelector).build());
+
+        // The INT intent installation order can be random, so we need to collect
+        // all expected INT intents and check if actual intent exists.
+        assertEquals(5, intentMap.size());
+        intentMap.entrySet().forEach(entry -> {
+            IntIntent actualIntIntent = entry.getValue().value();
+            assertTrue(expectedIntIntents.contains(actualIntIntent));
+        });
     }
 
     @Test
diff --git a/apps/inbandtelemetry/impl/src/test/resources/report-config.json b/apps/inbandtelemetry/impl/src/test/resources/report-config.json
index c0c1ca2..366aeab 100644
--- a/apps/inbandtelemetry/impl/src/test/resources/report-config.json
+++ b/apps/inbandtelemetry/impl/src/test/resources/report-config.json
@@ -1,5 +1,10 @@
 {
   "collectorIp": "10.0.0.1",
   "collectorPort": 32766,
-  "minFlowHopLatencyChangeNs": 32
+  "minFlowHopLatencyChangeNs": 32,
+  "watchSubnets": [
+    "0.0.0.0/0",
+    "192.168.10.0/24",
+    "192.168.20.0/24"
+  ]
 }
\ No newline at end of file