Packet throttle support

Change-Id: I6f2da5ed25f794561349013bfcbf9afa85d5e190
diff --git a/apps/packet-throttle/BUILD b/apps/packet-throttle/BUILD
new file mode 100644
index 0000000..581fd15
--- /dev/null
+++ b/apps/packet-throttle/BUILD
@@ -0,0 +1,12 @@
+BUNDLES = [
+    "//apps/packet-throttle/app:onos-apps-packet-throttle-app",
+]
+
+onos_app(
+    app_name = "org.onosproject.packetthrottle",
+    category = "Traffic Steering",
+    description = "Packet throttle application to make ONOS drop packets crossing threshold",
+    included_bundles = BUNDLES,
+    title = "Packet Throttler",
+    url = "http://onosproject.org",
+)
diff --git a/apps/packet-throttle/app/BUILD b/apps/packet-throttle/app/BUILD
new file mode 100644
index 0000000..75b3bd6
--- /dev/null
+++ b/apps/packet-throttle/app/BUILD
@@ -0,0 +1,10 @@
+COMPILE_DEPS = CORE_DEPS + CLI + [
+    "//core/store/serializers:onos-core-serializers",
+    "//core/store/primitives:onos-core-primitives",
+]
+
+osgi_jar_with_tests(
+    karaf_command_packages = ["org.onosproject.packetthrottle.cli"],
+    test_deps = TEST_ADAPTERS,
+    deps = COMPILE_DEPS,
+)
diff --git a/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/OsgiPropertyConstants.java b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/OsgiPropertyConstants.java
new file mode 100644
index 0000000..f2639ab
--- /dev/null
+++ b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/OsgiPropertyConstants.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.packetthrottle;
+
+/**
+ * Constants for default values of configurable properties.
+ */
+public final class OsgiPropertyConstants {
+
+    private OsgiPropertyConstants() {}
+
+    public static final String PROP_PPS_ARP = "ppsArp";
+    public static final int PPS_ARP_DEFAULT = 100;
+
+    public static final String PROP_PPS_DHCP = "ppsDhcp";
+    public static final int PPS_DHCP_DEFAULT = 100;
+
+    public static final String PROP_PPS_NS = "ppsNs";
+    public static final int PPS_NS_DEFAULT = 100;
+
+    public static final String PROP_PPS_NA = "ppsNa";
+    public static final int PPS_NA_DEFAULT = 100;
+
+    public static final String PROP_PPS_DHCP6_DIRECT = "ppsDhcp6Direct";
+    public static final int PPS_DHCP6_DIRECT_DEFAULT = 100;
+
+    public static final String PROP_PPS_DHCP6_INDIRECT = "ppsDhcp6Indirect";
+    public static final int PPS_DHCP6_INDIRECT_DEFAULT = 100;
+
+    public static final String PROP_PPS_ICMP = "ppsIcmp";
+    public static final int PPS_ICMP_DEFAULT = 100;
+
+    public static final String PROP_PPS_ICMP6 = "ppsIcmp6";
+    public static final int PPS_ICMP6_DEFAULT = 100;
+
+    public static final String PROP_WIN_SIZE_ARP_MS = "winSizeArp";
+    public static final int WIN_SIZE_ARP_MS_DEFAULT = 500;
+
+    public static final String PROP_WIN_SIZE_DHCP_MS = "winSizeDhcp";
+    public static final int WIN_SIZE_DHCP_MS_DEFAULT = 500;
+
+    public static final String PROP_WIN_SIZE_NA_MS = "winSizeNa";
+    public static final int WIN_SIZE_NA_MS_DEFAULT = 500;
+
+    public static final String PROP_WIN_SIZE_NS_MS = "winSizeNs";
+    public static final int WIN_SIZE_NS_MS_DEFAULT = 500;
+
+    public static final String PROP_WIN_SIZE_DHCP6_DIRECT_MS = "winSizeDhcp6Direct";
+    public static final int WIN_SIZE_DHCP6_DIRECT_MS_DEFAULT = 500;
+
+    public static final String PROP_WIN_SIZE_DHCP6_INDIRECT_MS = "winSizeDhcp6Indirect";
+    public static final int WIN_SIZE_DHCP6_INDIRECT_MS_DEFAULT = 500;
+
+    public static final String PROP_WIN_SIZE_ICMP_MS = "winSizeIcmp";
+    public static final int WIN_SIZE_ICMP_MS_DEFAULT = 500;
+
+    public static final String PROP_WIN_SIZE_ICMP6_MS = "winSizeIcmp6";
+    public static final int WIN_SIZE_ICMP6_MS_DEFAULT = 500;
+
+    public static final String PROP_GUARD_TIME_ARP_SEC = "guardTimeArp";
+    public static final int GUARD_TIME_ARP_SEC_DEFAULT = 10;
+
+    public static final String PROP_GUARD_TIME_DHCP_SEC = "guardTimeDhcp";
+    public static final int GUARD_TIME_DHCP_SEC_DEFAULT = 10;
+
+    public static final String PROP_GUARD_TIME_NS_SEC = "guardTimeNs";
+    public static final int GUARD_TIME_NS_SEC_DEFAULT = 10;
+
+    public static final String PROP_GUARD_TIME_NA_SEC = "guardTimeNa";
+    public static final int GUARD_TIME_NA_SEC_DEFAULT = 10;
+
+    public static final String PROP_GUARD_TIME_DHCP6_DIRECT_SEC = "guardTimeDhcp6Direct";
+    public static final int GUARD_TIME_DHCP6_DIRECT_SEC_DEFAULT = 10;
+
+    public static final String PROP_GUARD_TIME_DHCP6_INDIRECT_SEC = "guardTimeDhcp6Indirect";
+    public static final int GUARD_TIME_DHCP6_INDIRECT_SEC_DEFAULT = 10;
+
+    public static final String PROP_GUARD_TIME_ICMP_SEC = "guardTimeIcmp";
+    public static final int GUARD_TIME_ICMP_SEC_DEFAULT = 10;
+
+    public static final String PROP_GUARD_TIME_ICMP6_SEC = "guardTimeIcmp6";
+    public static final int GUARD_TIME_ICMP6_SEC_DEFAULT = 10;
+
+    public static final String PROP_WIN_THRES_ARP = "winThresArp";
+    public static final int WIN_THRES_ARP_DEFAULT = 10;
+
+    public static final String PROP_WIN_THRES_DHCP = "winThresDhcp";
+    public static final int WIN_THRES_DHCP_DEFAULT = 10;
+
+    public static final String PROP_WIN_THRES_NS = "winThresNs";
+    public static final int WIN_THRES_NS_DEFAULT = 10;
+
+    public static final String PROP_WIN_THRES_NA = "winThresNa";
+    public static final int WIN_THRES_NA_DEFAULT = 10;
+
+    public static final String PROP_WIN_THRES_DHCP6_DIRECT = "winThresDhcp6Direct";
+    public static final int WIN_THRES_DHCP6_DIRECT_DEFAULT = 10;
+
+    public static final String PROP_WIN_THRES_DHCP6_INDIRECT = "winThresDhcp6Indirect";
+    public static final int WIN_THRES_DHCP6_INDIRECT_DEFAULT = 10;
+
+    public static final String PROP_WIN_THRES_ICMP = "winThresIcmp";
+    public static final int WIN_THRES_ICMP_DEFAULT = 10;
+
+    public static final String PROP_WIN_THRES_ICMP6 = "winThresIcmp6";
+    public static final int WIN_THRES_ICMP6_DEFAULT = 10;
+
+}
diff --git a/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/PacketThrottleManager.java b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/PacketThrottleManager.java
new file mode 100644
index 0000000..76ff093
--- /dev/null
+++ b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/PacketThrottleManager.java
@@ -0,0 +1,666 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.packetthrottle;
+
+import com.google.common.collect.ImmutableMap;
+import org.osgi.service.component.annotations.Modified;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Deactivate;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.net.packet.PacketInFilter;
+import org.onosproject.net.packet.PacketService;
+import org.onosproject.net.packet.packetfilter.DefaultPacketInFilter;
+import org.onosproject.net.packet.packetfilter.ArpPacketClassifier;
+import org.onosproject.net.packet.packetfilter.Dhcp6IndirectPacketClassifier;
+import org.onosproject.net.packet.packetfilter.Dhcp6DirectPacketClassifier;
+import org.onosproject.net.packet.packetfilter.DhcpPacketClassifier;
+import org.onosproject.net.packet.packetfilter.NAPacketClassifier;
+import org.onosproject.net.packet.packetfilter.NSPacketClassifier;
+import org.onosproject.net.packet.packetfilter.IcmpPacketClassifier;
+import org.onosproject.net.packet.packetfilter.Icmp6PacketClassifier;
+import org.onosproject.packetthrottle.api.PacketThrottleService;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_PPS_ARP;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PPS_ARP_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_PPS_DHCP;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PPS_DHCP_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_PPS_NS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PPS_NS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_PPS_NA;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PPS_NA_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_PPS_DHCP6_DIRECT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PPS_DHCP6_DIRECT_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_PPS_DHCP6_INDIRECT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PPS_DHCP6_INDIRECT_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_PPS_ICMP;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PPS_ICMP_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_PPS_ICMP6;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PPS_ICMP6_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_SIZE_ARP_MS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_SIZE_ARP_MS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_SIZE_DHCP_MS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_SIZE_DHCP_MS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_SIZE_NA_MS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_SIZE_NA_MS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_SIZE_NS_MS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_SIZE_NS_MS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_SIZE_DHCP6_DIRECT_MS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_SIZE_DHCP6_DIRECT_MS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_SIZE_DHCP6_INDIRECT_MS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_SIZE_DHCP6_INDIRECT_MS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_SIZE_ICMP_MS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_SIZE_ICMP_MS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_SIZE_ICMP6_MS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_SIZE_ICMP6_MS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_GUARD_TIME_ARP_SEC;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.GUARD_TIME_ARP_SEC_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_GUARD_TIME_DHCP_SEC;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.GUARD_TIME_DHCP_SEC_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_GUARD_TIME_NS_SEC;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.GUARD_TIME_NS_SEC_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_GUARD_TIME_NA_SEC;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.GUARD_TIME_NA_SEC_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_GUARD_TIME_DHCP6_DIRECT_SEC;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.GUARD_TIME_DHCP6_DIRECT_SEC_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_GUARD_TIME_DHCP6_INDIRECT_SEC;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.GUARD_TIME_DHCP6_INDIRECT_SEC_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_GUARD_TIME_ICMP_SEC;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.GUARD_TIME_ICMP_SEC_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_GUARD_TIME_ICMP6_SEC;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.GUARD_TIME_ICMP6_SEC_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_THRES_ARP;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_THRES_ARP_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_THRES_DHCP;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_THRES_DHCP_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_THRES_NS;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_THRES_NS_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_THRES_NA;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_THRES_NA_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_THRES_DHCP6_DIRECT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_THRES_DHCP6_DIRECT_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_THRES_DHCP6_INDIRECT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_THRES_DHCP6_INDIRECT_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_THRES_ICMP;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_THRES_ICMP_DEFAULT;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.PROP_WIN_THRES_ICMP6;
+import static org.onosproject.packetthrottle.OsgiPropertyConstants.WIN_THRES_ICMP6_DEFAULT;
+
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onlab.util.Tools.get;
+
+/**
+ * Manage the packet throttle for various type of packets.
+ */
+@Component(
+        immediate = true,
+        service = PacketThrottleService.class,
+        property = {
+                PROP_PPS_ARP + ":Integer=" + PPS_ARP_DEFAULT,
+                PROP_PPS_DHCP + ":Integer=" + PPS_DHCP_DEFAULT,
+                PROP_PPS_NS + ":Integer=" + PPS_NS_DEFAULT,
+                PROP_PPS_NA + ":Integer=" + PPS_NA_DEFAULT,
+                PROP_PPS_DHCP6_DIRECT + ":Integer=" + PPS_DHCP6_DIRECT_DEFAULT,
+                PROP_PPS_DHCP6_INDIRECT + ":Integer=" + PPS_DHCP6_INDIRECT_DEFAULT,
+                PROP_PPS_ICMP + ":Integer=" + PPS_ICMP_DEFAULT,
+                PROP_PPS_ICMP6 + ":Integer=" + PPS_ICMP6_DEFAULT,
+                PROP_WIN_SIZE_ARP_MS + ":Integer=" + WIN_SIZE_ARP_MS_DEFAULT,
+                PROP_WIN_SIZE_DHCP_MS + ":Integer=" + WIN_SIZE_DHCP_MS_DEFAULT,
+                PROP_WIN_SIZE_NA_MS + ":Integer=" + WIN_SIZE_NA_MS_DEFAULT,
+                PROP_WIN_SIZE_NS_MS + ":Integer=" + WIN_SIZE_NS_MS_DEFAULT,
+                PROP_WIN_SIZE_DHCP6_DIRECT_MS + ":Integer=" + WIN_SIZE_DHCP6_DIRECT_MS_DEFAULT,
+                PROP_WIN_SIZE_DHCP6_INDIRECT_MS + ":Integer=" + WIN_SIZE_DHCP6_INDIRECT_MS_DEFAULT,
+                PROP_WIN_SIZE_ICMP_MS + ":Integer=" + WIN_SIZE_ICMP_MS_DEFAULT,
+                PROP_WIN_SIZE_ICMP6_MS + ":Integer=" + WIN_SIZE_ICMP6_MS_DEFAULT,
+                PROP_GUARD_TIME_ARP_SEC + ":Integer=" + GUARD_TIME_ARP_SEC_DEFAULT,
+                PROP_GUARD_TIME_DHCP_SEC + ":Integer=" + GUARD_TIME_DHCP_SEC_DEFAULT,
+                PROP_GUARD_TIME_NS_SEC + ":Integer=" + GUARD_TIME_NS_SEC_DEFAULT,
+                PROP_GUARD_TIME_NA_SEC + ":Integer=" + GUARD_TIME_NA_SEC_DEFAULT,
+                PROP_GUARD_TIME_DHCP6_DIRECT_SEC + ":Integer=" + GUARD_TIME_DHCP6_DIRECT_SEC_DEFAULT,
+                PROP_GUARD_TIME_DHCP6_INDIRECT_SEC + ":Integer=" + GUARD_TIME_DHCP6_INDIRECT_SEC_DEFAULT,
+                PROP_GUARD_TIME_ICMP_SEC + ":Integer=" + GUARD_TIME_ICMP_SEC_DEFAULT,
+                PROP_GUARD_TIME_ICMP6_SEC + ":Integer=" + GUARD_TIME_ICMP6_SEC_DEFAULT,
+                PROP_WIN_THRES_ARP + ":Integer=" + WIN_THRES_ARP_DEFAULT,
+                PROP_WIN_THRES_DHCP + ":Integer=" + WIN_THRES_DHCP_DEFAULT,
+                PROP_WIN_THRES_NS + ":Integer=" + WIN_THRES_NS_DEFAULT,
+                PROP_WIN_THRES_NA + ":Integer=" + WIN_THRES_NA_DEFAULT,
+                PROP_WIN_THRES_DHCP6_DIRECT + ":Integer=" + WIN_THRES_DHCP6_DIRECT_DEFAULT,
+                PROP_WIN_THRES_DHCP6_INDIRECT + ":Integer=" + WIN_THRES_DHCP6_INDIRECT_DEFAULT,
+                PROP_WIN_THRES_ICMP + ":Integer=" + WIN_THRES_ICMP_DEFAULT,
+                PROP_WIN_THRES_ICMP6 + ":Integer=" + WIN_THRES_ICMP6_DEFAULT
+        }
+)
+public class PacketThrottleManager implements PacketThrottleService {
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    protected static final String ARP_FILTER = "arpFilter";
+    protected static final String DHCP_FILTER = "dhcpFilter";
+    protected static final String NS_FILTER = "nsFilter";
+    protected static final String NA_FILTER = "naFilter";
+    protected static final String DHCP6_DIRECT_FILTER = "dhcp6DirectFilter";
+    protected static final String DHCP6_INDIRECT_FILTER = "dhcp6IndirectFilter";
+    protected static final String ICMP_FILTER = "icmpFilter";
+    protected static final String ICMP6_FILTER = "icmp6Filter";
+
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    PacketService packetService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected ComponentConfigService configService;
+
+    /**
+     * Parameter to set packet per second rate for all filter types.
+     */
+
+    private int ppsArp = PPS_ARP_DEFAULT;
+
+    private int ppsDhcp = PPS_DHCP_DEFAULT;
+
+    private int ppsNs = PPS_NS_DEFAULT;
+
+    private int ppsNa = PPS_NA_DEFAULT;
+
+    private int ppsDhcp6Direct = PPS_DHCP6_DIRECT_DEFAULT;
+
+    private int ppsDhcp6Indirect = PPS_DHCP6_INDIRECT_DEFAULT;
+
+    private int ppsIcmp = PPS_ICMP_DEFAULT;
+
+    private int ppsIcmp6 = PPS_ICMP6_DEFAULT;
+
+
+    /**
+     * Parameter to set window size in milli seconds to check overflow of packets.
+     */
+
+    private int winSizeArp = WIN_SIZE_ARP_MS_DEFAULT;
+
+    private int winSizeDhcp = WIN_SIZE_DHCP_MS_DEFAULT;
+
+    private int winSizeNs = WIN_SIZE_NS_MS_DEFAULT;
+
+    private int winSizeNa = WIN_SIZE_NA_MS_DEFAULT;
+
+    private int winSizeDhcp6Direct = WIN_SIZE_DHCP6_DIRECT_MS_DEFAULT;
+
+    private int winSizeDhcp6Indirect = WIN_SIZE_DHCP6_INDIRECT_MS_DEFAULT;
+
+    private int winSizeIcmp = WIN_SIZE_ICMP_MS_DEFAULT;
+
+    private int winSizeIcmp6 = WIN_SIZE_ICMP6_MS_DEFAULT;
+
+    /**
+     * Time duration for which no more packets will be processed for a given filter type
+     * provided consecutive overflow windows happens.
+     */
+
+
+    private int guardTimeArp = GUARD_TIME_ARP_SEC_DEFAULT;
+
+    private int guardTimeDhcp = GUARD_TIME_DHCP_SEC_DEFAULT;
+
+    private int guardTimeNs = GUARD_TIME_NS_SEC_DEFAULT;
+
+    private int guardTimeNa = GUARD_TIME_NA_SEC_DEFAULT;
+
+    private int guardTimeDhcp6Direct = GUARD_TIME_DHCP6_DIRECT_SEC_DEFAULT;
+
+    private int guardTimeDhcp6Indirect = GUARD_TIME_DHCP6_INDIRECT_SEC_DEFAULT;
+
+    private int guardTimeIcmp = GUARD_TIME_ICMP_SEC_DEFAULT;
+
+    private int guardTimeIcmp6 = GUARD_TIME_ICMP6_SEC_DEFAULT;
+
+    /**
+     * Consecutive overflow window threshold.
+     */
+
+
+    private int winThresArp = WIN_THRES_ARP_DEFAULT;
+
+    private int winThresDhcp = WIN_THRES_DHCP_DEFAULT;
+
+    private int winThresNs = WIN_THRES_NS_DEFAULT;
+
+    private int winThresNa = WIN_THRES_NA_DEFAULT;
+
+    private int winThresDhcp6Direct = WIN_THRES_DHCP6_DIRECT_DEFAULT;
+
+    private int winThresDhcp6Indirect = WIN_THRES_DHCP6_INDIRECT_DEFAULT;
+
+    private int winThresIcmp = WIN_THRES_ICMP_DEFAULT;
+
+    private int winThresIcmp6 = WIN_THRES_ICMP6_DEFAULT;
+
+
+
+
+    private Map<String, PacketInFilter> mapCounterFilter = new HashMap<>();
+
+    @Activate
+    protected void activate() {
+        log.info("Started");
+        configService.registerProperties(getClass());
+        createAllFilters();
+    }
+
+    @Deactivate
+    protected void deactivate() {
+        configService.unregisterProperties(getClass(), false);
+        removeAllFilters();
+        log.info("Stopped");
+    }
+
+    private void checkChangeInPps(ComponentContext context) {
+        Dictionary<?, ?> properties = context.getProperties();
+        int newPpsArp, newPpsDhcp, newPpsNs, newPpsNa, newPpsDhcp6Direct;
+        int newPpsDhcp6Indirect, newPpsIcmp, newPpsIcmp6;
+        try {
+            String s = get(properties, PROP_PPS_ARP);
+            newPpsArp = isNullOrEmpty(s) ? ppsArp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_PPS_DHCP);
+            newPpsDhcp = isNullOrEmpty(s) ? ppsDhcp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_PPS_NS);
+            newPpsNs = isNullOrEmpty(s) ? ppsNs : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_PPS_NA);
+            newPpsNa = isNullOrEmpty(s) ? ppsNa : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_PPS_DHCP6_DIRECT);
+            newPpsDhcp6Direct = isNullOrEmpty(s) ? ppsDhcp6Direct : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_PPS_DHCP6_INDIRECT);
+            newPpsDhcp6Indirect = isNullOrEmpty(s) ? ppsDhcp6Indirect : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_PPS_ICMP);
+            newPpsIcmp = isNullOrEmpty(s) ? ppsIcmp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_PPS_ICMP6);
+            newPpsIcmp6 = isNullOrEmpty(s) ? ppsIcmp6 : Integer.parseInt(s.trim());
+        } catch (NumberFormatException | ClassCastException e) {
+            newPpsArp = PPS_ARP_DEFAULT;
+            newPpsDhcp = PPS_DHCP_DEFAULT;
+            newPpsNs = PPS_NS_DEFAULT;
+            newPpsNa = PPS_NA_DEFAULT;
+            newPpsDhcp6Direct = PPS_DHCP6_DIRECT_DEFAULT;
+            newPpsDhcp6Indirect = PPS_DHCP6_INDIRECT_DEFAULT;
+            newPpsIcmp = PPS_ICMP_DEFAULT;
+            newPpsIcmp6 = PPS_ICMP6_DEFAULT;
+        }
+        if (newPpsArp != ppsArp) {
+            ppsArp = newPpsArp;
+            mapCounterFilter.get(ARP_FILTER).setPps(ppsArp);
+        }
+        if (newPpsDhcp != ppsDhcp) {
+            ppsDhcp = newPpsDhcp;
+            mapCounterFilter.get(DHCP_FILTER).setPps(ppsDhcp);
+        }
+        if (newPpsNs != ppsNs) {
+            ppsNs = newPpsNs;
+            mapCounterFilter.get(NS_FILTER).setPps(ppsNs);
+        }
+        if (newPpsNa != ppsNa) {
+            ppsNa = newPpsNa;
+            mapCounterFilter.get(NA_FILTER).setPps(ppsNa);
+        }
+        if (newPpsDhcp6Direct != ppsDhcp6Direct) {
+            ppsDhcp6Direct = newPpsDhcp6Direct;
+            mapCounterFilter.get(DHCP6_DIRECT_FILTER).setPps(ppsDhcp6Direct);
+        }
+        if (newPpsDhcp6Indirect != ppsDhcp6Indirect) {
+            ppsDhcp6Indirect = newPpsDhcp6Indirect;
+            mapCounterFilter.get(DHCP6_INDIRECT_FILTER).setPps(ppsDhcp6Indirect);
+        }
+        if (newPpsIcmp != ppsIcmp) {
+            ppsIcmp = newPpsIcmp;
+            mapCounterFilter.get(ICMP_FILTER).setPps(ppsIcmp);
+        }
+        if (newPpsIcmp6 != ppsIcmp6) {
+            ppsIcmp6 = newPpsIcmp6;
+            mapCounterFilter.get(ICMP6_FILTER).setPps(ppsIcmp6);
+        }
+    }
+
+    private void checkChangeInWinSize(ComponentContext context) {
+        Dictionary<?, ?> properties = context.getProperties();
+
+        int newWinSizeArp, newWinSizeDhcp, newWinSizeNs, newWinSizeNa;
+        int newWinSizeDhcp6Direct, newWinSizeDhcp6Indirect, newWinSizeIcmp, newWinSizeIcmp6;
+        try {
+            String s = get(properties, PROP_WIN_SIZE_ARP_MS);
+            newWinSizeArp = isNullOrEmpty(s) ? winSizeArp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_SIZE_DHCP_MS);
+            newWinSizeDhcp = isNullOrEmpty(s) ? winSizeDhcp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_SIZE_NS_MS);
+            newWinSizeNs = isNullOrEmpty(s) ? winSizeNs : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_SIZE_NA_MS);
+            newWinSizeNa = isNullOrEmpty(s) ? winSizeNa : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_SIZE_DHCP6_DIRECT_MS);
+            newWinSizeDhcp6Direct = isNullOrEmpty(s) ? winSizeDhcp6Direct : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_SIZE_DHCP6_INDIRECT_MS);
+            newWinSizeDhcp6Indirect = isNullOrEmpty(s) ? winSizeDhcp6Indirect : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_SIZE_ICMP_MS);
+            newWinSizeIcmp = isNullOrEmpty(s) ? winSizeIcmp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_SIZE_ICMP6_MS);
+            newWinSizeIcmp6 = isNullOrEmpty(s) ? winSizeIcmp6 : Integer.parseInt(s.trim());
+        } catch (NumberFormatException | ClassCastException e) {
+            newWinSizeArp = WIN_SIZE_ARP_MS_DEFAULT;
+            newWinSizeDhcp = WIN_SIZE_DHCP_MS_DEFAULT;
+            newWinSizeNs = WIN_SIZE_NS_MS_DEFAULT;
+            newWinSizeNa = WIN_SIZE_NA_MS_DEFAULT;
+            newWinSizeDhcp6Direct = WIN_SIZE_DHCP6_DIRECT_MS_DEFAULT;
+            newWinSizeDhcp6Indirect = WIN_SIZE_DHCP6_INDIRECT_MS_DEFAULT;
+            newWinSizeIcmp = WIN_SIZE_ICMP_MS_DEFAULT;
+            newWinSizeIcmp6 = WIN_SIZE_ICMP6_MS_DEFAULT;
+        }
+        if (newWinSizeArp != winSizeArp) {
+            winSizeArp = newWinSizeArp;
+            mapCounterFilter.get(ARP_FILTER).setWinSize(winSizeArp);
+        }
+        if (newWinSizeDhcp != winSizeDhcp) {
+            winSizeDhcp = newWinSizeDhcp;
+            mapCounterFilter.get(DHCP_FILTER).setWinSize(winSizeDhcp);
+        }
+        if (newWinSizeNs != winSizeNs) {
+            winSizeNs = newWinSizeNs;
+            mapCounterFilter.get(NS_FILTER).setWinSize(winSizeNs);
+        }
+        if (newWinSizeNa != winSizeNa) {
+            winSizeNa = newWinSizeNa;
+            mapCounterFilter.get(NA_FILTER).setWinSize(winSizeNa);
+        }
+        if (newWinSizeDhcp6Direct != winSizeDhcp6Direct) {
+            winSizeDhcp6Direct = newWinSizeDhcp6Direct;
+            mapCounterFilter.get(DHCP6_DIRECT_FILTER).setWinSize(winSizeDhcp6Direct);
+        }
+        if (newWinSizeDhcp6Indirect != winSizeDhcp6Indirect) {
+            winSizeDhcp6Indirect = newWinSizeDhcp6Indirect;
+            mapCounterFilter.get(DHCP6_INDIRECT_FILTER).setWinSize(winSizeDhcp6Indirect);
+        }
+        if (newWinSizeIcmp != winSizeIcmp) {
+            winSizeIcmp = newWinSizeIcmp;
+            mapCounterFilter.get(ICMP_FILTER).setWinSize(winSizeIcmp);
+        }
+        if (newWinSizeIcmp6 != winSizeIcmp6) {
+            winSizeIcmp6 = newWinSizeIcmp6;
+            mapCounterFilter.get(ICMP6_FILTER).setWinSize(winSizeIcmp6);
+        }
+
+    }
+
+    private void checkChangeInGuardTime(ComponentContext context) {
+        Dictionary<?, ?> properties = context.getProperties();
+        int newGuardTimeArp, newGuardTimeDhcp, newGuardTimeNs, newGuardTimeNa;
+        int newGuardTimeDhcp6Direct, newGuardTimeDhcp6Indirect, newGuardTimeIcmp, newGuardTimeIcmp6;
+        try {
+            String s = get(properties, PROP_GUARD_TIME_ARP_SEC);
+            newGuardTimeArp = isNullOrEmpty(s) ? guardTimeArp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_GUARD_TIME_DHCP_SEC);
+            newGuardTimeDhcp = isNullOrEmpty(s) ? guardTimeDhcp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_GUARD_TIME_NS_SEC);
+            newGuardTimeNs = isNullOrEmpty(s) ? guardTimeNs : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_GUARD_TIME_NA_SEC);
+            newGuardTimeNa = isNullOrEmpty(s) ? guardTimeNa : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_GUARD_TIME_DHCP6_DIRECT_SEC);
+            newGuardTimeDhcp6Direct = isNullOrEmpty(s) ? guardTimeDhcp6Direct : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_GUARD_TIME_DHCP6_INDIRECT_SEC);
+            newGuardTimeDhcp6Indirect = isNullOrEmpty(s) ? guardTimeDhcp6Indirect : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_GUARD_TIME_ICMP_SEC);
+            newGuardTimeIcmp = isNullOrEmpty(s) ? guardTimeIcmp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_GUARD_TIME_ICMP6_SEC);
+            newGuardTimeIcmp6 = isNullOrEmpty(s) ? guardTimeIcmp6 : Integer.parseInt(s.trim());
+        } catch (NumberFormatException | ClassCastException e) {
+
+            newGuardTimeArp = GUARD_TIME_ARP_SEC_DEFAULT;
+            newGuardTimeDhcp = GUARD_TIME_DHCP_SEC_DEFAULT;
+            newGuardTimeNs = GUARD_TIME_NS_SEC_DEFAULT;
+            newGuardTimeNa = GUARD_TIME_NA_SEC_DEFAULT;
+            newGuardTimeDhcp6Direct = GUARD_TIME_DHCP6_DIRECT_SEC_DEFAULT;
+            newGuardTimeDhcp6Indirect = GUARD_TIME_DHCP6_INDIRECT_SEC_DEFAULT;
+            newGuardTimeIcmp = GUARD_TIME_ICMP_SEC_DEFAULT;
+            newGuardTimeIcmp6 = GUARD_TIME_ICMP6_SEC_DEFAULT;
+        }
+        if (newGuardTimeArp != guardTimeArp) {
+            guardTimeArp = newGuardTimeArp;
+            mapCounterFilter.get(ARP_FILTER).setGuardTime(guardTimeArp);
+        }
+        if (newGuardTimeDhcp != guardTimeDhcp) {
+            guardTimeDhcp = newGuardTimeDhcp;
+            mapCounterFilter.get(DHCP_FILTER).setGuardTime(guardTimeDhcp);
+        }
+        if (newGuardTimeNs != guardTimeNs) {
+            guardTimeNs = newGuardTimeNs;
+            mapCounterFilter.get(NS_FILTER).setGuardTime(guardTimeNs);
+        }
+        if (newGuardTimeNa != guardTimeNa) {
+            guardTimeNa = newGuardTimeNa;
+            mapCounterFilter.get(NA_FILTER).setGuardTime(guardTimeNa);
+        }
+        if (newGuardTimeDhcp6Direct != guardTimeDhcp6Direct) {
+            guardTimeDhcp6Direct = newGuardTimeDhcp6Direct;
+            mapCounterFilter.get(DHCP6_DIRECT_FILTER).setGuardTime(guardTimeDhcp6Direct);
+        }
+        if (newGuardTimeDhcp6Indirect != guardTimeDhcp6Indirect) {
+            guardTimeDhcp6Indirect = newGuardTimeDhcp6Indirect;
+            mapCounterFilter.get(DHCP6_INDIRECT_FILTER).setGuardTime(guardTimeDhcp6Indirect);
+        }
+        if (newGuardTimeIcmp != guardTimeIcmp) {
+            guardTimeIcmp = newGuardTimeIcmp;
+            mapCounterFilter.get(ICMP_FILTER).setGuardTime(guardTimeIcmp);
+        }
+        if (newGuardTimeIcmp6 != guardTimeIcmp6) {
+            guardTimeIcmp6 = newGuardTimeIcmp6;
+            mapCounterFilter.get(ICMP6_FILTER).setGuardTime(guardTimeIcmp6);
+        }
+
+
+    }
+
+    private void checkChangeInWinThres(ComponentContext context) {
+        Dictionary<?, ?> properties = context.getProperties();
+
+        int newWinThresArp, newWinThresDhcp, newWinThresNs, newWinThresNa;
+        int newWinThresDhcp6Direct, newWinThresDhcp6Indirect, newWinThresIcmp, newWinThresIcmp6;
+        try {
+
+            String s = get(properties, PROP_WIN_THRES_ARP);
+            newWinThresArp = isNullOrEmpty(s) ? winThresArp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_THRES_DHCP);
+            newWinThresDhcp = isNullOrEmpty(s) ? winThresDhcp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_THRES_NS);
+            newWinThresNs = isNullOrEmpty(s) ? winThresNs : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_THRES_NA);
+            newWinThresNa = isNullOrEmpty(s) ? winThresNa : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_THRES_DHCP6_DIRECT);
+            newWinThresDhcp6Direct = isNullOrEmpty(s) ? winThresDhcp6Direct : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_THRES_DHCP6_INDIRECT);
+            newWinThresDhcp6Indirect = isNullOrEmpty(s) ? winThresDhcp6Indirect : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_THRES_ICMP);
+            newWinThresIcmp = isNullOrEmpty(s) ? winThresIcmp : Integer.parseInt(s.trim());
+
+            s = get(properties, PROP_WIN_THRES_ICMP6);
+            newWinThresIcmp6 = isNullOrEmpty(s) ? winThresIcmp6 : Integer.parseInt(s.trim());
+
+        } catch (NumberFormatException | ClassCastException e) {
+            newWinThresArp = WIN_THRES_ARP_DEFAULT;
+            newWinThresDhcp = WIN_THRES_DHCP_DEFAULT;
+            newWinThresNs = WIN_THRES_NS_DEFAULT;
+            newWinThresNa = WIN_THRES_NA_DEFAULT;
+            newWinThresDhcp6Direct = WIN_THRES_DHCP6_DIRECT_DEFAULT;
+            newWinThresDhcp6Indirect = WIN_THRES_DHCP6_INDIRECT_DEFAULT;
+            newWinThresIcmp = WIN_THRES_ICMP_DEFAULT;
+            newWinThresIcmp6 = WIN_THRES_ICMP6_DEFAULT;
+
+        }
+
+        if (newWinThresArp != winThresArp) {
+            winThresArp = newWinThresArp;
+            mapCounterFilter.get(ARP_FILTER).setWinThres(winThresArp);
+        }
+        if (newWinThresDhcp != winThresDhcp) {
+            winThresDhcp = newWinThresDhcp;
+            mapCounterFilter.get(DHCP_FILTER).setWinThres(winThresDhcp);
+        }
+        if (newWinThresNs != winThresNs) {
+            winThresNs = newWinThresNs;
+            mapCounterFilter.get(NS_FILTER).setWinThres(winThresNs);
+        }
+        if (newWinThresNa != winThresNa) {
+            winThresNa = newWinThresNa;
+            mapCounterFilter.get(NA_FILTER).setWinThres(winThresNa);
+        }
+        if (newWinThresDhcp6Direct != winThresDhcp6Direct) {
+            winThresDhcp6Direct = newWinThresDhcp6Direct;
+            mapCounterFilter.get(DHCP6_DIRECT_FILTER).setWinThres(winThresDhcp6Direct);
+        }
+        if (newWinThresDhcp6Indirect != winThresDhcp6Indirect) {
+            winThresDhcp6Indirect = newWinThresDhcp6Indirect;
+            mapCounterFilter.get(DHCP6_INDIRECT_FILTER).setWinThres(winThresDhcp6Indirect);
+        }
+        if (newWinThresIcmp != winThresIcmp) {
+            winThresIcmp = newWinThresIcmp;
+            mapCounterFilter.get(ICMP_FILTER).setWinThres(winThresIcmp);
+        }
+        if (newWinThresIcmp6 != winThresIcmp6) {
+            winThresIcmp6 = newWinThresIcmp6;
+            mapCounterFilter.get(ICMP6_FILTER).setWinThres(winThresIcmp6);
+        }
+
+    }
+
+    @Modified
+    private void modified(ComponentContext context) {
+        if (context == null) {
+            log.info("Default config");
+            return;
+        }
+
+        checkChangeInPps(context);
+        checkChangeInWinSize(context);
+        checkChangeInGuardTime(context);
+        checkChangeInWinThres(context);
+
+        log.info("Reconfigured ppsArp: {} ppsDhcp: {} ppsNs: {} ppsNa: {} " +
+                "ppsDhcp6Direct: {} ppsDhcp6Indirect: {} ppsIcmp: {} ppsIcmp6: {}",
+                 ppsArp, ppsDhcp, ppsNs, ppsNa, ppsDhcp6Direct, ppsDhcp6Indirect,
+                 ppsIcmp, ppsIcmp6);
+
+        log.info("Reconfigured winSizeArp: {} winSizeDhcp: {} winSizeNs: {} winSizeNa: {} " +
+                 "winSizeDhcp6Direct: {} winSizeDhcp6Indirect: {} winSizeIcmp: {} winSizeIcmp6: {}",
+                 winSizeArp, winSizeDhcp, winSizeNs, winSizeNa, winSizeDhcp6Direct,
+                 winSizeDhcp6Indirect, winSizeIcmp, winSizeIcmp6);
+
+        log.info("Reconfigured guardTimeArp: {} guardTimeDhcp: {} guardTimeNs: {} guardTimeNa: {} " +
+                 "guardTimeDhcp6Direct: {} guardTimeDhcp6Indirect: {} guardTimeIcmp: {} guardTimeIcmp6: {}",
+                 guardTimeArp, guardTimeDhcp, guardTimeNs, guardTimeNa, guardTimeDhcp6Direct,
+                 guardTimeDhcp6Indirect, guardTimeIcmp, guardTimeIcmp6);
+
+        log.info("Reconfigured winThresArp: {} winThresDhcp: {} winThresNs: {} winThresNa: {} " +
+                 "winThresDhcp6Direct: {} winThresDhcp6Indirect: {} winThresIcmp: {} winThresIcmp6: {}",
+                 winThresArp, winThresDhcp, winThresNs, winThresNa, winThresDhcp6Direct,
+                 winThresDhcp6Indirect, winThresIcmp, winThresIcmp6);
+    }
+
+    /**
+     * Create all required filters.
+     */
+    private void createAllFilters() {
+        DefaultPacketInFilter filter;
+        ArpPacketClassifier arp = new ArpPacketClassifier();
+        filter = new DefaultPacketInFilter(ppsArp, winSizeArp, guardTimeArp, winThresArp, ARP_FILTER, arp);
+        packetService.addFilter(filter);
+        mapCounterFilter.put(filter.name(), filter);
+        DhcpPacketClassifier dhcp4 = new DhcpPacketClassifier();
+        filter = new DefaultPacketInFilter(ppsDhcp, winSizeDhcp, guardTimeDhcp, winThresDhcp, DHCP_FILTER, dhcp4);
+        packetService.addFilter(filter);
+        mapCounterFilter.put(filter.name(), filter);
+        Dhcp6DirectPacketClassifier dhcp6Direct = new Dhcp6DirectPacketClassifier();
+        filter = new DefaultPacketInFilter(ppsDhcp6Direct, winSizeDhcp6Direct, guardTimeDhcp6Direct,
+                                           winThresDhcp6Direct, DHCP6_DIRECT_FILTER, dhcp6Direct);
+        packetService.addFilter(filter);
+        mapCounterFilter.put(filter.name(), filter);
+        Dhcp6IndirectPacketClassifier dhcp6Indirect = new Dhcp6IndirectPacketClassifier();
+        filter = new DefaultPacketInFilter(ppsDhcp6Direct, winSizeDhcp6Direct, guardTimeDhcp6Direct,
+                                           winThresDhcp6Direct, DHCP6_INDIRECT_FILTER, dhcp6Indirect);
+        packetService.addFilter(filter);
+        mapCounterFilter.put(filter.name(), filter);
+        NAPacketClassifier na = new NAPacketClassifier();
+        filter = new DefaultPacketInFilter(ppsNa, winSizeNa, guardTimeNa, winThresNa, NA_FILTER, na);
+        packetService.addFilter(filter);
+        mapCounterFilter.put(filter.name(), filter);
+        NSPacketClassifier ns = new NSPacketClassifier();
+        filter = new DefaultPacketInFilter(ppsNs, winSizeNs, guardTimeNs, winThresNs, NS_FILTER, ns);
+        packetService.addFilter(filter);
+        mapCounterFilter.put(filter.name(), filter);
+        IcmpPacketClassifier icmp = new IcmpPacketClassifier();
+        filter = new DefaultPacketInFilter(ppsIcmp, winSizeIcmp, guardTimeIcmp, winThresIcmp, ICMP_FILTER, icmp);
+        packetService.addFilter(filter);
+        mapCounterFilter.put(filter.name(), filter);
+        Icmp6PacketClassifier icmp6 = new Icmp6PacketClassifier();
+        filter = new DefaultPacketInFilter(ppsIcmp6, winSizeIcmp6, guardTimeIcmp6, winThresIcmp6, ICMP6_FILTER, icmp6);
+        packetService.addFilter(filter);
+        mapCounterFilter.put(filter.name(), filter);
+    }
+
+    /**
+     * Delete all the filters.
+     */
+    private void removeAllFilters() {
+        packetService.clearFilters();
+        mapCounterFilter.clear();
+    }
+
+    @Override
+    public Map<String, PacketInFilter> filterMap() {
+        return ImmutableMap.copyOf(mapCounterFilter);
+    }
+
+
+
+}
diff --git a/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/api/PacketThrottleService.java b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/api/PacketThrottleService.java
new file mode 100644
index 0000000..80abbdc
--- /dev/null
+++ b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/api/PacketThrottleService.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.packetthrottle.api;
+
+import org.onosproject.net.packet.PacketInFilter;
+import java.util.Map;
+
+public interface PacketThrottleService {
+
+    /**
+     * Returns all avaiable packet filters.
+     * @return all packet filters
+     */
+    Map<String, PacketInFilter> filterMap();
+
+}
diff --git a/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/api/package-info.java b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/api/package-info.java
new file mode 100644
index 0000000..220deb0
--- /dev/null
+++ b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/api/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Packet throttle application.
+ */
+package org.onosproject.packetthrottle.api;
\ No newline at end of file
diff --git a/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/cli/PacketOverFlowStatsShowCommand.java b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/cli/PacketOverFlowStatsShowCommand.java
new file mode 100644
index 0000000..2fd9192
--- /dev/null
+++ b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/cli/PacketOverFlowStatsShowCommand.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.packetthrottle.cli;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.onosproject.net.packet.PacketInFilter;
+import org.onosproject.packetthrottle.api.PacketThrottleService;
+import java.util.Map;
+
+
+/**
+ * Displays the statistics of the packets dropped due to throttle.
+ */
+@Service
+@Command(scope = "onos", name = "pkt-stats-overflow-show",
+        description = "Displays the packet overflow statistics values")
+public class PacketOverFlowStatsShowCommand extends AbstractShellCommand {
+
+    private static final String FORMAT = "PacketType = %s, Count = %s";
+
+
+
+    @Override
+    protected void doExecute() {
+        PacketInFilter filter;
+        PacketThrottleService packetThrottleService = get(PacketThrottleService.class);
+        Map<String, PacketInFilter> filterMap = packetThrottleService.filterMap();
+        for (Map.Entry<String, PacketInFilter> entry: filterMap.entrySet()) {
+            filter = entry.getValue();
+            print(FORMAT, filter.name(), filter.droppedPackets());
+        }
+    }
+}
diff --git a/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/cli/package-info.java b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/cli/package-info.java
new file mode 100644
index 0000000..e94b5a4
--- /dev/null
+++ b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/cli/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Packet throttle application.
+ */
+package org.onosproject.packetthrottle.cli;
diff --git a/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/package-info.java b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/package-info.java
new file mode 100644
index 0000000..ba0df46
--- /dev/null
+++ b/apps/packet-throttle/app/src/main/java/org/onosproject/packetthrottle/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Packet throttle application.
+ */
+package org.onosproject.packetthrottle;
\ No newline at end of file
diff --git a/apps/packet-throttle/app/src/test/java/org/onosproject/packetthrottle/PacketThrottleManagerTest.java b/apps/packet-throttle/app/src/test/java/org/onosproject/packetthrottle/PacketThrottleManagerTest.java
new file mode 100644
index 0000000..4582a43
--- /dev/null
+++ b/apps/packet-throttle/app/src/test/java/org/onosproject/packetthrottle/PacketThrottleManagerTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.packetthrottle;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.cfg.ComponentConfigAdapter;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketServiceAdapter;
+import org.onosproject.net.packet.PacketInFilter;
+import com.google.common.collect.Sets;
+import org.onosproject.net.packet.packetfilter.ArpPacketClassifier;
+import org.onosproject.net.packet.packetfilter.DefaultPacketInFilter;
+import static org.junit.Assert.*;
+
+
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.List;
+
+/**
+ * Set of tests of the PacketThrottleManager.
+ */
+public class PacketThrottleManagerTest {
+
+    private PacketThrottleManager manager;
+
+
+    @Before
+    public void setUp() {
+        manager = new PacketThrottleManager();
+        manager.configService = new TestComponentConfig();
+        manager.packetService = new MockPacketService();
+        manager.activate();
+    }
+
+    @After
+    public void tearDown() {
+        manager.deactivate();
+    }
+
+    @Test
+    public void testFilter() {
+        DefaultPacketInFilter filter;
+        ArpPacketClassifier arp = new ArpPacketClassifier();
+        filter = new DefaultPacketInFilter(100, 500, 10, 10, PacketThrottleManager.ARP_FILTER, arp);
+        manager.packetService.addFilter(filter);
+        assertEquals(9, manager.packetService.getFilters().size());
+        manager.packetService.removeFilter(filter);
+        assertEquals(8, manager.packetService.getFilters().size());
+    }
+
+    private class MockPacketService extends PacketServiceAdapter {
+        Set<PacketProcessor> packetProcessors = Sets.newHashSet();
+        OutboundPacket emittedPacket;
+        private List<PacketInFilter> filters = new ArrayList<>();
+
+        @Override
+        public void addProcessor(PacketProcessor processor, int priority) {
+
+            packetProcessors.add(processor);
+        }
+
+        public void processPacket(PacketContext packetContext) {
+            packetProcessors.forEach(p -> p.process(packetContext));
+        }
+
+        @Override
+        public void emit(OutboundPacket packet) {
+
+            this.emittedPacket = packet;
+        }
+
+        @Override
+        public void addFilter(PacketInFilter filter) {
+            filters.add(filter);
+        }
+
+        @Override
+        public void removeFilter(PacketInFilter filter) {
+            filters.remove(filter);
+        }
+
+        @Override
+        public List<PacketInFilter> getFilters() {
+            return ImmutableList.copyOf(filters);
+        }
+    }
+
+    /**
+     * Mocks the ComponentConfigRegistry.
+     */
+    private class TestComponentConfig extends ComponentConfigAdapter {
+
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/PacketInClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/PacketInClassifier.java
new file mode 100644
index 0000000..34c7502
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/PacketInClassifier.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+
+/**
+ * Abstraction of incoming packet classifier for filtering.
+ */
+public interface PacketInClassifier {
+
+    /**
+     * Returns true if the packet classifier matches else false.
+     * The matching criterion should be non overlapping with other
+     * implementation of the PacketInClassifier.
+     *
+     * @param packet PacketContext holding the packet information
+     * @return boolean checks whether packet matches classifier
+     */
+    boolean match(PacketContext packet);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/PacketInFilter.java b/core/api/src/main/java/org/onosproject/net/packet/PacketInFilter.java
new file mode 100644
index 0000000..1338b05
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/PacketInFilter.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet;
+
+/**
+ * Abstraction of incoming packet filter.
+ */
+public interface PacketInFilter {
+
+    /**
+     * Types of filter action applied to incoming packets.
+     */
+    enum FilterAction {
+        /**
+         * Signifies that the packet is allowed to be processed.
+         */
+        PACKET_ALLOW,
+        /**
+         * Signifies that the packet is denied from being processed
+         * as it crossed the maxCounter.
+         */
+        PACKET_DENY,
+        /**
+         * Signifies that filter applied is a valid filter.
+         */
+        FILTER_VALID,
+        /**
+         * Signifies that this filter is disabled.
+         */
+        FILTER_DISABLED,
+        /**
+         * Signifies that the current window for packet processing is full
+         * and the window is blocked for packet processing.
+         */
+        WINDOW_BLOCKED,
+        /**
+         * Signifies that the packet processing is blocked as the
+         * threshold has crossed.
+         */
+        PACKET_BLOCKED,
+        /**
+         * Signifies that the filter applied is invalid filter.
+         */
+        FILTER_INVALID
+    }
+
+    /**
+     * Returns FilterAction before processing the packet.
+     * Decides if the packet is allowed to be processed or not.
+     *
+     * @param packet PackerContext holding the packet information
+     * @return FilterAction
+     */
+    FilterAction preProcess(PacketContext packet);
+
+    /**
+     * Get the name of the counter.
+     *
+     * @return name of the counter
+     */
+    String name();
+
+    /**
+     * Get the current value of the count of packets for this particular
+     * filter type waiting to get processed.
+     *
+     * @return count of packets with current filter type waiting to get processed
+     */
+    int pendingPackets();
+
+    /**
+     * Get the count of the dropped packets for this filter type.
+     *
+     * @return count of dropped packets for this filter type
+     */
+    int droppedPackets();
+
+    /**
+     * Set the pps rate for the current filter type to calculate the max counter
+     * allowed with window size.
+     *
+     * @param pps Packet per second rate expected
+     */
+    void setPps(int pps);
+
+    /**
+     * Set the window size for rate limiting.
+     *
+     * @param winSize Window size in milli seconds
+     */
+    void setWinSize(int winSize);
+
+    /**
+     * Set the Guard time in case WinThres is crossed.
+     *
+     * @param guardTime Guard time in  seconds
+     */
+    void setGuardTime(int guardTime);
+
+    /**
+     * Set the Window Threshold for dropping the packet.
+     *
+     * @param winThres Threshold count of the consecutive windows with packet drops
+     */
+    void setWinThres(int winThres);
+
+    /**
+     * Stop the threads running for this filter.
+     *
+     */
+    void stop();
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/PacketService.java b/core/api/src/main/java/org/onosproject/net/packet/PacketService.java
index 56889a5..21ecd49 100644
--- a/core/api/src/main/java/org/onosproject/net/packet/PacketService.java
+++ b/core/api/src/main/java/org/onosproject/net/packet/PacketService.java
@@ -19,6 +19,7 @@
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.flow.TrafficSelector;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
@@ -52,6 +53,22 @@
     void removeProcessor(PacketProcessor processor);
 
     /**
+     * Adds the specified filter to the list of packet filters.
+     * It will be added into the list in the order in which it is added.
+     *
+     * @param filter filter to be added
+     */
+    default void addFilter(PacketInFilter filter) {}
+
+
+    /**
+     * Removes the specified filter from the filters list.
+     *
+     * @param filter filter to be removed
+     */
+    default void removeFilter(PacketInFilter filter) {}
+
+    /**
      * Returns priority bindings of all registered packet processor entries.
      *
      * @return list of existing packet processor entries
@@ -123,4 +140,20 @@
      */
     void emit(OutboundPacket packet);
 
+    /**
+     * Get the list of packet filters present in ONOS.
+     *
+     * @return List of packet filters
+     */
+    default List<PacketInFilter> getFilters() {
+        return new ArrayList<>();
+    }
+
+    /**
+     * Clear all packet filters in one shot.
+     *
+     */
+    default void clearFilters() {}
+
+
 }
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/ArpPacketClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/ArpPacketClassifier.java
new file mode 100644
index 0000000..5aed044
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/ArpPacketClassifier.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onlab.packet.ARP;
+import org.onlab.packet.Ethernet;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+
+public class ArpPacketClassifier implements PacketInClassifier {
+
+    @Override
+    public boolean match(PacketContext packet) {
+
+        Ethernet eth = packet.inPacket().parsed();
+        if (eth != null && (eth.getEtherType() == Ethernet.TYPE_ARP)) {
+            ARP arpPacket = (ARP) eth.getPayload();
+            if (arpPacket.getOpCode() == ARP.OP_REQUEST) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/DefaultPacketInFilter.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/DefaultPacketInFilter.java
new file mode 100644
index 0000000..d628f80
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/DefaultPacketInFilter.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+import org.onosproject.net.packet.PacketInFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.onlab.util.Tools.groupedThreads;
+
+/**
+ * Default implementation of a packet-in filter.
+ */
+public class DefaultPacketInFilter implements PacketInFilter {
+
+    /**
+     * Tracks the count of specific packet types (eg ARP, ND, DHCP etc)
+     * to be limited in the packet queue. This count always reflects the
+     * number of packets in the queue at any point in time
+     */
+    private AtomicInteger currentCounter = new AtomicInteger(0);
+
+    /**
+     * Tracks the number of continuous windows where the drop packet happens.
+     */
+    private AtomicInteger windowBlockCounter = new AtomicInteger(0);
+
+    /**
+     * Tracks the counter of the packet which are dropped.
+     */
+    private AtomicInteger overFlowCounter = new AtomicInteger(0);
+
+    private final Logger log = LoggerFactory.getLogger(getClass());
+
+    /**
+     * Max Allowed packet rate beyond which the packet will be dropped
+     * within given window size.
+     */
+    private int pps = 100;
+
+    /**
+     * Window size which will be used for number of packets acceptable
+     * based on the accepted pps.
+     */
+    private int winSize = 500;
+
+    /**
+     * Guard time in seconds which will be enabled if there are continuous
+     * windows crossing winThres where the packet rate crosses the acceptable
+     * packet count calculated based on accepted pps.
+     * Guard time should be always greater then the the window size.
+     */
+    private int guardTime = 10;
+
+    /**
+     * Threshold of continuous windows where the packet drop happens post which
+     * the guardTime will be triggered and no future packet processing happens
+     * till the expiry of this guard time.
+     */
+    private int winThres = 10;
+
+
+    private int maxCounter;
+
+    private ScheduledExecutorService timerExecutor;
+
+    private ScheduledExecutorService windowUnblockExecutor;
+
+    private boolean windowBlocked;
+
+    private boolean packetProcessingBlocked;
+
+
+    /**
+     * Name of the counter.
+     */
+    private String counterName;
+
+    /**
+     * PacketInclassifier associated with this filter object.
+     */
+    private final PacketInClassifier classifier;
+
+
+
+    /**
+     * Only one filter object per packet type to be associated.
+     * Multiple filter types will result in undefined behavior.
+     * @param pps Rate at which the packet is accepted in packets per second
+     * @param winSize Size of window in milli seconds within which
+     *                the packet rate will be analyzed
+     * @param guardTime Time duration in seconds for which the packet processing
+     *                  will be on hold if there is a continuous window where
+     *                  cross of the rate happens and that window count crosses
+     *                  winThres
+     * @param winThres Continuous window threshold after which gaurdTime will be
+     *                 activated
+     * @param counterName Name of the counter
+     * @param classifier Packet classification
+     */
+    public DefaultPacketInFilter(int pps, int winSize, int guardTime, int winThres,
+                                 String counterName, PacketInClassifier classifier) {
+        this.pps = pps;
+        this.winSize = winSize;
+        this.guardTime = guardTime;
+        this.winThres = winThres;
+        this.counterName = counterName;
+        this.classifier = classifier;
+        this.maxCounter = (pps * winSize) / 1000;
+        timerExecutor = Executors.newScheduledThreadPool(1,
+                                                         groupedThreads("packet/packetfilter",
+                                                                        "packet-filter-timer-%d", log));
+
+        windowUnblockExecutor = Executors.newScheduledThreadPool(1,
+                                                                 groupedThreads("packet/packetfilter",
+                                                                                "packet-filter-unblocker-%d", log));
+        timerExecutor.scheduleAtFixedRate(new ClearWindowBlock(),
+                                          0,
+                                          winSize,
+                                          TimeUnit.MILLISECONDS);
+
+
+        windowBlocked = false;
+        packetProcessingBlocked = false;
+
+    }
+
+
+
+    @Override
+    public FilterAction preProcess(PacketContext packet) {
+
+
+        maxCounter = (pps * winSize) / 1000;
+
+        // If pps is set then min value for maxCounter is 1
+        if (maxCounter == 0 && pps != 0) {
+            log.trace("{}: maxCounter set to 1 as was coming as 0", counterName);
+            maxCounter = 1;
+        }
+
+
+
+        if (!classifier.match(packet)) {
+            return FilterAction.FILTER_INVALID;
+        }
+
+        if (pps == 0 && maxCounter == 0) {
+            log.trace("{}: Filter is disabled", counterName);
+            return FilterAction.FILTER_DISABLED;
+        }
+        log.trace("{}: Preprocess called", counterName);
+
+        // Packet block checking should be done before windowBlocked checking
+        // otherwise there will be windows with packets while packet processing is suspended
+        // and that may break the existing check logic
+        if (packetProcessingBlocked) {
+            log.trace("{}: Packet processing is blocked for sometime", counterName);
+            return FilterAction.PACKET_BLOCKED;
+        }
+
+        if (windowBlocked) {
+            log.trace("{}: Packet processing is blocked for the window number: {}",
+                      counterName, windowBlockCounter.get());
+            return FilterAction.WINDOW_BLOCKED;
+        }
+
+        if (currentCounter.getAndIncrement() < maxCounter) {
+            log.trace("{}: Packet is picked for processing with currentCounter: {} and maxCounter: {}",
+                      counterName, currentCounter.get(), maxCounter);
+            return FilterAction.PACKET_ALLOW;
+        }
+        //Need to decrement the currentCounter and increment overFlowCounter
+        //Need to block the window and increment the window block counter
+        windowBlocked = true;
+        //TODO: Review this and the complete state machine
+        // If windowBlock crosses threshold then block packet processing for guard time
+        if (windowBlockCounter.incrementAndGet() > winThres) {
+            log.trace("{}: Packet processing blocked as current window crossed threshold " +
+                       "currentWindowNumber: {} maxWindowNumber: {}",
+                       counterName, windowBlockCounter.get(), winThres);
+            packetProcessingBlocked = true;
+            windowUnblockExecutor.schedule(new ClearPacketProcessingBlock(),
+                                                         guardTime,
+                                                         TimeUnit.SECONDS);
+        } else {
+            log.trace("{}: WindowBlockCounter: {} winThres: {}", counterName, windowBlockCounter.get(),
+            winThres);
+        }
+        //MT: Temp change in logic to branch the code - Rolled back
+        currentCounter.decrementAndGet();
+        if (overFlowCounter.incrementAndGet() < 0) {
+            overFlowCounter.set(0);
+        }
+        log.trace("{}: Overflow counter is: {}", counterName, overFlowCounter.get());
+        return FilterAction.PACKET_DENY;
+
+    }
+
+    @Override
+    public String name() {
+        return counterName;
+    }
+
+    @Override
+    public int pendingPackets() {
+        return currentCounter.get();
+    }
+
+    @Override
+    public int droppedPackets() {
+       return overFlowCounter.get();
+    }
+
+
+
+    @Override
+    public void setPps(int pps) {
+        this.pps = pps;
+    }
+
+    @Override
+    public void setWinSize(int winSize) {
+        this.winSize = winSize;
+    }
+
+    @Override
+    public void setGuardTime(int guardTime) {
+        this.guardTime = guardTime;
+    }
+
+    @Override
+    public void setWinThres(int winThres) {
+        this.winThres = winThres;
+    }
+
+    @Override
+    public void stop() {
+        timerExecutor.shutdown();
+        windowUnblockExecutor.shutdown();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        DefaultPacketInFilter that = (DefaultPacketInFilter) o;
+        return pps == that.pps &&
+                winSize == that.winSize &&
+                guardTime == that.guardTime &&
+                winThres == that.winThres &&
+                counterName.equals(that.counterName) &&
+                classifier.equals(that.classifier);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(pps, winSize, guardTime, winThres, counterName, classifier);
+    }
+
+
+    private final class ClearWindowBlock implements Runnable {
+        @Override
+        public void run() {
+            // If window is not already blocked and there is at least one packet processed
+            // in that window then reset the window block counter:
+            if (!windowBlocked) {
+                log.trace("{}: WindowBlockCounter is reset as there was no blocking in current " +
+                          "window with current windowBlockCounter: {}", counterName, windowBlockCounter.get());
+                windowBlockCounter.set(0);
+            }
+            if (currentCounter.get() == 0) {
+                //No packet processed in current window so do not change anything in the current state
+                log.trace("{}: No packets in the current window so not doing anything in ClearWindowBlock",
+                          counterName);
+                return;
+            }
+
+            //Reset the counter and unblock the window
+            log.trace("{}: Current counter and windowBlocked is reset in ClearWindowBlock", counterName);
+            currentCounter.set(0);
+            windowBlocked = false;
+        }
+    }
+
+    private final class ClearPacketProcessingBlock implements Runnable {
+        @Override
+        public void run() {
+            //Reset the counter and unblock the window and packet processing
+            //CurrentCounter and windowBlocked counter setting is not required here
+            //Still setting to be on safer side
+            log.trace("{}: All blocks cleared in ClearPacketProcessingBlock", counterName);
+            currentCounter.set(0);
+            windowBlocked = false;
+            packetProcessingBlocked = false;
+            windowBlockCounter.set(0);
+        }
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Dhcp6DirectPacketClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Dhcp6DirectPacketClassifier.java
new file mode 100644
index 0000000..a320a44
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Dhcp6DirectPacketClassifier.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onlab.packet.DHCP6;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv6;
+import org.onlab.packet.UDP;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class Dhcp6DirectPacketClassifier implements PacketInClassifier {
+    private final Logger log = getLogger(getClass());
+    @Override
+    public boolean match(PacketContext packet) {
+
+        Ethernet eth = packet.inPacket().parsed();
+
+        if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
+            IPv6 ipv6Packet = (IPv6) eth.getPayload();
+
+            if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_UDP) {
+                UDP udpPacket = (UDP) ipv6Packet.getPayload();
+                //Directly connected host
+                if (udpPacket.getDestinationPort() == UDP.DHCP_V6_SERVER_PORT &&
+                        udpPacket.getSourcePort() == UDP.DHCP_V6_CLIENT_PORT) {
+                    DHCP6 dhcp6 = (DHCP6) udpPacket.getPayload();
+                    if (dhcp6.getMsgType() == DHCP6.MsgType.SOLICIT.value()) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Dhcp6IndirectPacketClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Dhcp6IndirectPacketClassifier.java
new file mode 100644
index 0000000..afb2c31
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Dhcp6IndirectPacketClassifier.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onlab.packet.BasePacket;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv6;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.DHCP6;
+import org.onlab.packet.UDP;
+import org.onlab.packet.dhcp.Dhcp6RelayOption;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+import org.slf4j.Logger;
+
+import java.util.Arrays;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class Dhcp6IndirectPacketClassifier implements PacketInClassifier {
+    private final Logger log = getLogger(getClass());
+
+    @Override
+    public boolean match(PacketContext packet) {
+
+        Ethernet eth = packet.inPacket().parsed();
+
+        if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
+            IPv6 ipv6Packet = (IPv6) eth.getPayload();
+
+            if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_UDP) {
+                UDP udpPacket = (UDP) ipv6Packet.getPayload();
+                //Indirectly connected host
+                if (udpPacket.getDestinationPort() == UDP.DHCP_V6_SERVER_PORT &&
+                        udpPacket.getSourcePort() == UDP.DHCP_V6_SERVER_PORT &&
+                        Arrays.equals(ipv6Packet.getDestinationAddress(),
+                                Ip6Address.valueOf("ff02::1:2").toOctets())) {
+                    DHCP6 relayMessage = (DHCP6) udpPacket.getPayload();
+                    DHCP6 dhcp6 = (DHCP6) relayMessage.getOptions().stream()
+                            .filter(opt -> opt instanceof Dhcp6RelayOption)
+                            .map(BasePacket::getPayload)
+                            .map(pld -> (DHCP6) pld)
+                            .findFirst()
+                            .orElse(null);
+
+                    if (dhcp6.getMsgType() == DHCP6.MsgType.SOLICIT.value()) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/DhcpPacketClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/DhcpPacketClassifier.java
new file mode 100644
index 0000000..1389c8c
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/DhcpPacketClassifier.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onlab.packet.DHCP;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.UDP;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+
+public class DhcpPacketClassifier implements PacketInClassifier {
+
+    @Override
+    public boolean match(PacketContext packet) {
+
+        Ethernet eth = packet.inPacket().parsed();
+
+        if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
+            IPv4 ipv4Packet = (IPv4) eth.getPayload();
+
+            if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_UDP) {
+                UDP udpPacket = (UDP) ipv4Packet.getPayload();
+
+                if (udpPacket.getDestinationPort() == UDP.DHCP_SERVER_PORT &&
+                        udpPacket.getSourcePort() == UDP.DHCP_CLIENT_PORT) {
+                    DHCP dhcp = (DHCP) udpPacket.getPayload();
+                    if (dhcp.getPacketType() == DHCP.MsgType.DHCPDISCOVER) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Icmp6PacketClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Icmp6PacketClassifier.java
new file mode 100644
index 0000000..7dfa806
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/Icmp6PacketClassifier.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP6;
+import org.onlab.packet.IPv6;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class Icmp6PacketClassifier implements PacketInClassifier {
+    private final Logger log = getLogger(getClass());
+    @Override
+    public boolean match(PacketContext packet) {
+        Ethernet eth = packet.inPacket().parsed();
+
+        if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
+            IPv6 ipv6Packet = (IPv6) eth.getPayload();
+
+            if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
+                ICMP6 icmp6Packet = (ICMP6) ipv6Packet.getPayload();
+                if (icmp6Packet.getIcmpType() == ICMP6.ECHO_REQUEST) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/IcmpPacketClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/IcmpPacketClassifier.java
new file mode 100644
index 0000000..501357c
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/IcmpPacketClassifier.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP;
+import org.onlab.packet.IPv4;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+
+public class IcmpPacketClassifier implements PacketInClassifier {
+
+    @Override
+    public boolean match(PacketContext packet) {
+
+        Ethernet eth = packet.inPacket().parsed();
+
+        if (eth.getEtherType() == Ethernet.TYPE_IPV4) {
+            IPv4 ipv4Packet = (IPv4) eth.getPayload();
+
+            if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_ICMP) {
+                ICMP icmpPacket = (ICMP) ipv4Packet.getPayload();
+                if (icmpPacket.getIcmpType() == ICMP.TYPE_ECHO_REQUEST) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/NAPacketClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/NAPacketClassifier.java
new file mode 100644
index 0000000..2dc653c
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/NAPacketClassifier.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP6;
+import org.onlab.packet.IPv6;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+
+public class NAPacketClassifier implements PacketInClassifier {
+
+    @Override
+    public boolean match(PacketContext packet) {
+
+        Ethernet eth = packet.inPacket().parsed();
+
+        if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
+            IPv6 ipv6Packet = (IPv6) eth.getPayload();
+            if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
+                ICMP6 icmp6 = (ICMP6) ipv6Packet.getPayload();
+                if (icmp6.getIcmpType() == ICMP6.NEIGHBOR_ADVERTISEMENT) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/NSPacketClassifier.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/NSPacketClassifier.java
new file mode 100644
index 0000000..4d90ada
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/NSPacketClassifier.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.packet.packetfilter;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP6;
+import org.onlab.packet.IPv6;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketInClassifier;
+
+public class NSPacketClassifier implements PacketInClassifier {
+
+    @Override
+    public boolean match(PacketContext packet) {
+
+        Ethernet eth = packet.inPacket().parsed();
+
+        if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
+            IPv6 ipv6Packet = (IPv6) eth.getPayload();
+            if (ipv6Packet.getNextHeader() == IPv6.PROTOCOL_ICMP6) {
+                ICMP6 icmp6 = (ICMP6) ipv6Packet.getPayload();
+                if (icmp6.getIcmpType() == ICMP6.NEIGHBOR_SOLICITATION) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/packet/packetfilter/package-info.java b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/package-info.java
new file mode 100644
index 0000000..2918caf
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/packet/packetfilter/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Packet filter classifier for various Packet types.
+ */
+package org.onosproject.net.packet.packetfilter;
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/net/packet/PacketServiceAdapter.java b/core/api/src/test/java/org/onosproject/net/packet/PacketServiceAdapter.java
index 5a1dfd5..10fa7e2 100644
--- a/core/api/src/test/java/org/onosproject/net/packet/PacketServiceAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/packet/PacketServiceAdapter.java
@@ -69,4 +69,9 @@
     @Override
     public void emit(OutboundPacket packet) {
     }
+
+    @Override
+    public List<PacketInFilter> getFilters() {
+        return null;
+    }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java b/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
index b9ac1a4..a020da7 100644
--- a/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
+++ b/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
@@ -59,12 +59,17 @@
 import org.osgi.service.component.annotations.Deactivate;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.onosproject.net.packet.PacketInFilter;
+import org.onosproject.net.packet.PacketInFilter.FilterAction;
 import org.slf4j.Logger;
 
 import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onlab.util.Tools.groupedThreads;
@@ -121,6 +126,8 @@
     private ApplicationId appId;
     private NodeId localNodeId;
 
+    private List<PacketInFilter> filters = new CopyOnWriteArrayList<>();
+
     @Activate
     public void activate() {
         eventHandlingExecutor = Executors.newSingleThreadExecutor(
@@ -189,6 +196,16 @@
     }
 
     @Override
+    public void addFilter(PacketInFilter filter) {
+        filters.add(filter);
+    }
+
+    @Override
+    public void removeFilter(PacketInFilter filter) {
+        filters.remove(filter);
+    }
+
+    @Override
     public List<PacketProcessorEntry> getProcessors() {
         checkPermission(PACKET_READ);
         return ImmutableList.copyOf(processors);
@@ -372,6 +389,19 @@
         store.emit(packet);
     }
 
+    @Override
+    public List<PacketInFilter> getFilters() {
+        return ImmutableList.copyOf(filters);
+    }
+
+    @Override
+    public void clearFilters() {
+        for (PacketInFilter filter: filters) {
+            filter.stop();
+        }
+        filters.clear();
+    }
+
     private void localEmit(OutboundPacket packet) {
         Device device = deviceService.getDevice(packet.sendThrough());
         if (device == null) {
@@ -399,8 +429,53 @@
             super(provider);
         }
 
+        /**
+         * Loops through all packet filters and checks if the filter is
+         * enabled and allowed to be processed.
+         * It increments the counter to track the pending packets to be
+         * processed based on the filter selected.
+         *
+         * @param context PackerContext holding the packet information
+         * @return FilterAction Action decided for the based on the filter applied
+         */
+        private FilterAction prePacketProcess(PacketContext context) {
+            FilterAction filterAction = FilterAction.FILTER_INVALID;
+            for (PacketInFilter filter: filters) {
+                filterAction = filter.preProcess(context);
+                if (filterAction == FilterAction.FILTER_DISABLED) {
+                    if (log.isTraceEnabled()) {
+                        log.trace("{}: filter is disabled during pre processing", filter.name());
+                    }
+                    continue;
+                }
+                if (filterAction == FilterAction.PACKET_DENY) {
+                    if (log.isTraceEnabled()) {
+                        log.trace("{}: overflow counter after dropping packet is: {}", filter.name(),
+                                filter.droppedPackets());
+                    }
+                    break;
+                }
+                if (filterAction == FilterAction.PACKET_ALLOW) {
+                    if (log.isTraceEnabled()) {
+                        log.trace("{}: counter after picked for processing is: {}", filter.name(),
+                                  filter.pendingPackets());
+                    }
+                    break;
+                }
+            }
+            return filterAction;
+        }
+
         @Override
         public void processPacket(PacketContext context) {
+            FilterAction filterAction = prePacketProcess(context);
+
+            if (filterAction == FilterAction.PACKET_DENY) {
+                if (log.isTraceEnabled()) {
+                    log.trace("The packet is dropped as crossed the maxcount");
+                }
+                return;
+            }
             // TODO filter packets sent to processors based on registrations
             for (ProcessorEntry entry : processors) {
                 try {
diff --git a/tools/build/bazel/modules.bzl b/tools/build/bazel/modules.bzl
index 0fb877e..9562206 100644
--- a/tools/build/bazel/modules.bzl
+++ b/tools/build/bazel/modules.bzl
@@ -252,6 +252,7 @@
     "//web/gui:onos-web-gui-oar",
     "//apps/workflow:onos-apps-workflow-oar",
     "//apps/workflow/ofoverlay:onos-apps-workflow-ofoverlay-oar",
+    "//apps/packet-throttle:onos-apps-packet-throttle-oar",
 ]
 
 PROTOCOL_APPS = [