ONOS-2145  Added ability to withdraw packet intercepts via PacketService::cancelPackets.

Change-Id: Ie41271fa02740560bd67b0faf49f633ee749773c
diff --git a/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java b/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
index b776280..0da1ae3 100644
--- a/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
+++ b/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
@@ -113,8 +113,8 @@
     private boolean hostRemovalEnabled = true;
 
     @Property(name = "ipv6NeighborDiscovery", boolValue = false,
-              label = "Enable using IPv6 Neighbor Discovery by the " +
-              "Host Location Provider; default is false")
+            label = "Enable using IPv6 Neighbor Discovery by the " +
+                    "Host Location Provider; default is false")
     private boolean ipv6NeighborDiscovery = false;
 
     /**
@@ -133,15 +133,17 @@
         packetService.addProcessor(processor, 1);
         deviceService.addListener(deviceListener);
         readComponentConfiguration(context);
-        requestPackests();
+        requestIntercepts();
 
         log.info("Started with Application ID {}", appId.id());
     }
 
     @Deactivate
     public void deactivate() {
-        // TODO revoke all packet requests when deactivate
         cfgService.unregisterProperties(getClass(), false);
+
+        withdrawIntercepts();
+
         providerRegistry.unregister(this);
         packetService.removeProcessor(processor);
         deviceService.removeListener(deviceListener);
@@ -151,38 +153,54 @@
 
     @Modified
     public void modified(ComponentContext context) {
-        // TODO revoke unnecessary packet requests when config being modified
         readComponentConfiguration(context);
-        requestPackests();
+        requestIntercepts();
     }
 
     /**
-     * Request packet in via PacketService.
+     * Request packet intercepts.
      */
-    private void requestPackests() {
-        TrafficSelector.Builder selectorBuilder =
-                DefaultTrafficSelector.builder();
-        selectorBuilder.matchEthType(Ethernet.TYPE_ARP);
-        packetService.requestPackets(selectorBuilder.build(),
-                                     PacketPriority.CONTROL, appId);
+    private void requestIntercepts() {
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        selector.matchEthType(Ethernet.TYPE_ARP);
+        packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
 
+        // IPv6 Neighbor Solicitation packet.
+        selector.matchEthType(Ethernet.TYPE_IPV6);
+        selector.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
+        selector.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
         if (ipv6NeighborDiscovery) {
-            // IPv6 Neighbor Solicitation packet.
-            selectorBuilder = DefaultTrafficSelector.builder();
-            selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
-            selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
-            selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
-            packetService.requestPackets(selectorBuilder.build(),
-                                         PacketPriority.CONTROL, appId);
-
-            // IPv6 Neighbor Advertisement packet.
-            selectorBuilder = DefaultTrafficSelector.builder();
-            selectorBuilder.matchEthType(Ethernet.TYPE_IPV6);
-            selectorBuilder.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
-            selectorBuilder.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
-            packetService.requestPackets(selectorBuilder.build(),
-                                         PacketPriority.CONTROL, appId);
+            packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
+        } else {
+            packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
         }
+
+        // IPv6 Neighbor Advertisement packet.
+        selector.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
+        if (ipv6NeighborDiscovery) {
+            packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
+        } else {
+            packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
+        }
+    }
+
+    /**
+     * Withdraw packet intercepts.
+     */
+    private void withdrawIntercepts() {
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        selector.matchEthType(Ethernet.TYPE_ARP);
+        packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
+
+        // IPv6 Neighbor Solicitation packet.
+        selector.matchEthType(Ethernet.TYPE_IPV6);
+        selector.matchIPProtocol(IPv6.PROTOCOL_ICMP6);
+        selector.matchIcmpv6Type(ICMP6.NEIGHBOR_SOLICITATION);
+        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
+
+        // IPv6 Neighbor Advertisement packet.
+        selector.matchIcmpv6Type(ICMP6.NEIGHBOR_ADVERTISEMENT);
+        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
     }
 
     /**
@@ -197,7 +215,7 @@
         flag = isPropertyEnabled(properties, "hostRemovalEnabled");
         if (flag == null) {
             log.info("Host removal on port/device down events is not configured, " +
-                     "using current value of {}", hostRemovalEnabled);
+                             "using current value of {}", hostRemovalEnabled);
         } else {
             hostRemovalEnabled = flag;
             log.info("Configured. Host removal on port/device down events is {}",
@@ -207,7 +225,7 @@
         flag = isPropertyEnabled(properties, "ipv6NeighborDiscovery");
         if (flag == null) {
             log.info("Using IPv6 Neighbor Discovery is not configured, " +
-                     "using current value of {}", ipv6NeighborDiscovery);
+                             "using current value of {}", ipv6NeighborDiscovery);
         } else {
             ipv6NeighborDiscovery = flag;
             log.info("Configured. Using IPv6 Neighbor Discovery is {}",
@@ -218,7 +236,7 @@
     /**
      * Check property name is defined and set to true.
      *
-     * @param properties properties to be looked up
+     * @param properties   properties to be looked up
      * @param propertyName the name of the property to look up
      * @return value when the propertyName is defined or return null
      */
@@ -244,24 +262,25 @@
         /**
          * Update host location only.
          *
-         * @param hid host ID
-         * @param mac source Mac address
+         * @param hid  host ID
+         * @param mac  source Mac address
          * @param vlan VLAN ID
          * @param hloc host location
          */
         private void updateLocation(HostId hid, MacAddress mac,
-                               VlanId vlan, HostLocation hloc) {
+                                    VlanId vlan, HostLocation hloc) {
             HostDescription desc = new DefaultHostDescription(mac, vlan, hloc);
             providerService.hostDetected(hid, desc);
         }
+
         /**
          * Update host location and IP address.
          *
-         * @param hid host ID
-         * @param mac source Mac address
+         * @param hid  host ID
+         * @param mac  source Mac address
          * @param vlan VLAN ID
          * @param hloc host location
-         * @param ip source IP address
+         * @param ip   source IP address
          */
         private void updateLocationIP(HostId hid, MacAddress mac,
                                       VlanId vlan, HostLocation hloc,
@@ -297,7 +316,7 @@
             }
 
             HostLocation hloc =
-                new HostLocation(heardOn, System.currentTimeMillis());
+                    new HostLocation(heardOn, System.currentTimeMillis());
 
             HostId hid = HostId.hostId(eth.getSourceMAC(), vlan);
 
@@ -308,19 +327,19 @@
                                                  arp.getSenderProtocolAddress());
                 updateLocationIP(hid, srcMac, vlan, hloc, ip);
 
-            // IPv4: update location only
+                // IPv4: update location only
             } else if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
                 updateLocation(hid, srcMac, vlan, hloc);
 
-            //
-            // NeighborAdvertisement and NeighborSolicitation: possible
-            // new hosts, update both location and IP.
-            //
-            // IPv6: update location only
+                //
+                // NeighborAdvertisement and NeighborSolicitation: possible
+                // new hosts, update both location and IP.
+                //
+                // IPv6: update location only
             } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
                 IPv6 ipv6 = (IPv6) eth.getPayload();
                 IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET6,
-                        ipv6.getSourceAddress());
+                                                 ipv6.getSourceAddress());
 
                 // skip extension headers
                 IPacket pkt = ipv6;
@@ -335,11 +354,11 @@
                     pkt = pkt.getPayload();
                     // RouterSolicitation, RouterAdvertisement
                     if (pkt != null && (pkt instanceof RouterAdvertisement ||
-                        pkt instanceof RouterSolicitation)) {
+                            pkt instanceof RouterSolicitation)) {
                         return;
                     }
                     if (pkt != null && (pkt instanceof NeighborSolicitation ||
-                        pkt instanceof NeighborAdvertisement)) {
+                            pkt instanceof NeighborAdvertisement)) {
                         // Duplicate Address Detection
                         if (ip.isZero()) {
                             return;
@@ -367,37 +386,37 @@
         public void event(DeviceEvent event) {
             Device device = event.subject();
             switch (event.type()) {
-            case DEVICE_ADDED:
-                break;
-            case DEVICE_AVAILABILITY_CHANGED:
-                if (hostRemovalEnabled &&
-                    !deviceService.isAvailable(device.id())) {
-                    removeHosts(hostService.getConnectedHosts(device.id()));
-                }
-                break;
-            case DEVICE_SUSPENDED:
-            case DEVICE_UPDATED:
-                // Nothing to do?
-                break;
-            case DEVICE_REMOVED:
-                if (hostRemovalEnabled) {
-                    removeHosts(hostService.getConnectedHosts(device.id()));
-                }
-                break;
-            case PORT_ADDED:
-                break;
-            case PORT_UPDATED:
-                if (hostRemovalEnabled) {
-                    ConnectPoint point =
-                        new ConnectPoint(device.id(), event.port().number());
-                    removeHosts(hostService.getConnectedHosts(point));
-                }
-                break;
-            case PORT_REMOVED:
-                // Nothing to do?
-                break;
-            default:
-                break;
+                case DEVICE_ADDED:
+                    break;
+                case DEVICE_AVAILABILITY_CHANGED:
+                    if (hostRemovalEnabled &&
+                            !deviceService.isAvailable(device.id())) {
+                        removeHosts(hostService.getConnectedHosts(device.id()));
+                    }
+                    break;
+                case DEVICE_SUSPENDED:
+                case DEVICE_UPDATED:
+                    // Nothing to do?
+                    break;
+                case DEVICE_REMOVED:
+                    if (hostRemovalEnabled) {
+                        removeHosts(hostService.getConnectedHosts(device.id()));
+                    }
+                    break;
+                case PORT_ADDED:
+                    break;
+                case PORT_UPDATED:
+                    if (hostRemovalEnabled) {
+                        ConnectPoint point =
+                                new ConnectPoint(device.id(), event.port().number());
+                        removeHosts(hostService.getConnectedHosts(point));
+                    }
+                    break;
+                case PORT_REMOVED:
+                    // Nothing to do?
+                    break;
+                default:
+                    break;
             }
         }
     }
diff --git a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
index 9f9c3b4..b9d9097 100644
--- a/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
+++ b/providers/host/src/test/java/org/onosproject/provider/host/impl/HostLocationProviderTest.java
@@ -15,27 +15,7 @@
  */
 package org.onosproject.provider.host.impl;
 
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.onlab.packet.VlanId.vlanId;
-import static org.onosproject.net.Device.Type.SWITCH;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.HostId.hostId;
-import static org.onosproject.net.PortNumber.portNumber;
-import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED;
-import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED;
-import static org.onosproject.net.device.DeviceEvent.Type.PORT_UPDATED;
-
-import java.nio.ByteBuffer;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Set;
-
+import com.google.common.collect.ImmutableSet;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -62,8 +42,6 @@
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceServiceAdapter;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.host.HostDescription;
 import org.onosproject.net.host.HostProvider;
@@ -74,15 +52,27 @@
 import org.onosproject.net.packet.InboundPacket;
 import org.onosproject.net.packet.OutboundPacket;
 import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketPriority;
 import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
+import org.onosproject.net.packet.PacketServiceAdapter;
 import org.onosproject.net.provider.AbstractProviderService;
 import org.onosproject.net.provider.ProviderId;
 import org.onosproject.net.topology.Topology;
 import org.onosproject.net.topology.TopologyServiceAdapter;
 
-import com.google.common.collect.ImmutableSet;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Set;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+import static org.onlab.packet.VlanId.vlanId;
+import static org.onosproject.net.Device.Type.SWITCH;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.HostId.hostId;
+import static org.onosproject.net.PortNumber.portNumber;
+import static org.onosproject.net.device.DeviceEvent.Type.*;
 
 public class HostLocationProviderTest {
 
@@ -143,7 +133,7 @@
 
         coreService = createMock(CoreService.class);
         expect(coreService.registerApplication(appId.name()))
-            .andReturn(appId).anyTimes();
+                .andReturn(appId).anyTimes();
         replay(coreService);
 
         provider.cfgService = new ComponentConfigAdapter();
@@ -271,31 +261,11 @@
 
     }
 
-    private class TestPacketService implements PacketService {
-
+    private class TestPacketService extends PacketServiceAdapter {
         @Override
         public void addProcessor(PacketProcessor processor, int priority) {
             testProcessor = processor;
         }
-
-        @Override
-        public void removeProcessor(PacketProcessor processor) {
-        }
-
-        @Override
-        public void emit(OutboundPacket packet) {
-        }
-
-        @Override
-        public void requestPackets(TrafficSelector selector,
-                                   PacketPriority priority, ApplicationId appId) {
-        }
-
-        @Override
-        public void requestPackets(TrafficSelector selector,
-                                   PacketPriority priority, ApplicationId appId,
-                                   FlowRule.Type tableType) {
-        }
     }
 
 
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
index 6a69af8..ec4a3ff 100644
--- a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
+++ b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
@@ -178,18 +178,20 @@
         executor = newSingleThreadScheduledExecutor(groupedThreads("onos/device", "sync-%d"));
         executor.scheduleAtFixedRate(new SyncDeviceInfoTask(), INIT_DELAY, DELAY, SECONDS);
 
-        requestPackets();
+        requestIntercepts();
 
         log.info("Started");
     }
 
     @Deactivate
     public void deactivate() {
-        // TODO revoke all packet requests when deactivate
         cfgService.unregisterProperties(getClass(), false);
         if (disableLinkDiscovery) {
             return;
         }
+
+        withdrawIntercepts();
+
         providerRegistry.unregister(this);
         deviceService.removeListener(listener);
         packetService.removeProcessor(listener);
@@ -205,7 +207,6 @@
 
     @Modified
     public void modified(ComponentContext context) {
-        // TODO revoke unnecessary packet requests when config being modified
         if (context == null) {
             loadSuppressionRules();
             return;
@@ -225,7 +226,7 @@
         if (!Strings.isNullOrEmpty(s)) {
             lldpSuppression = s;
         }
-
+        requestIntercepts();
         loadSuppressionRules();
     }
 
@@ -246,22 +247,33 @@
     }
 
     /**
-     * Request packet in via PacketService.
+     * Request packet intercepts.
      */
-    private void requestPackets() {
-        TrafficSelector.Builder lldpSelector = DefaultTrafficSelector.builder();
-        lldpSelector.matchEthType(Ethernet.TYPE_LLDP);
-        packetService.requestPackets(lldpSelector.build(),
-                                     PacketPriority.CONTROL, appId);
+    private void requestIntercepts() {
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        selector.matchEthType(Ethernet.TYPE_LLDP);
+        packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
 
+        selector.matchEthType(Ethernet.TYPE_BSN);
         if (useBDDP) {
-            TrafficSelector.Builder bddpSelector = DefaultTrafficSelector.builder();
-            bddpSelector.matchEthType(Ethernet.TYPE_BSN);
-            packetService.requestPackets(bddpSelector.build(),
-                                         PacketPriority.CONTROL, appId);
+            packetService.requestPackets(selector.build(), PacketPriority.CONTROL, appId);
+        } else {
+            packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
         }
     }
 
+    /**
+     * Withdraw packet intercepts.
+     */
+    private void withdrawIntercepts() {
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        selector.matchEthType(Ethernet.TYPE_LLDP);
+        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
+        selector.matchEthType(Ethernet.TYPE_BSN);
+        packetService.cancelPackets(selector.build(), PacketPriority.CONTROL, appId);
+    }
+
+
     private class InternalRoleListener implements MastershipListener {
 
         @Override
diff --git a/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java b/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
index f6627af..1d63a15 100644
--- a/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
+++ b/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
@@ -15,23 +15,9 @@
  */
 package org.onosproject.provider.lldp.impl;
 
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import java.nio.ByteBuffer;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -57,8 +43,6 @@
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceServiceAdapter;
-import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.link.LinkDescription;
 import org.onosproject.net.link.LinkProvider;
@@ -68,15 +52,21 @@
 import org.onosproject.net.packet.InboundPacket;
 import org.onosproject.net.packet.OutboundPacket;
 import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketPriority;
 import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
+import org.onosproject.net.packet.PacketServiceAdapter;
 import org.onosproject.net.provider.AbstractProviderService;
 import org.onosproject.net.provider.ProviderId;
 
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
 
 public class LLDPLinkProviderTest {
 
@@ -383,33 +373,11 @@
 
     }
 
-    private class TestPacketService implements PacketService {
-
+    private class TestPacketService extends PacketServiceAdapter {
         @Override
         public void addProcessor(PacketProcessor processor, int priority) {
             testProcessor = processor;
         }
-
-        @Override
-        public void removeProcessor(PacketProcessor processor) {
-
-        }
-
-        @Override
-        public void emit(OutboundPacket packet) {
-
-        }
-
-        @Override
-        public void requestPackets(TrafficSelector selector,
-                                   PacketPriority priority, ApplicationId appId) {
-        }
-
-        @Override
-        public void requestPackets(TrafficSelector selector,
-                                   PacketPriority priority, ApplicationId appId,
-                                   FlowRule.Type tableType) {
-        }
     }
 
     private class TestDeviceService extends DeviceServiceAdapter {
@@ -433,8 +401,6 @@
 
             ports.putAll(DID1, Lists.newArrayList(pd1, pd2));
             ports.putAll(DID2, Lists.newArrayList(pd3, pd4));
-
-
         }
 
         @Override