Use typed queues for OF message processing

Process OF messages through 8 queues. Output queue for messages
controlled per OF Agent with help of message classifiers.

Queues can be configured through component configuration mechanism
for "org.onosproject.openflow.controller.impl.OpenFlowControllerImpl"
component.

Classifiers can be configured through NetworkConfig API in the following
form:

      {
        "devices": {
           "of:0000000000000001": {
               "classifiers": [{
                   "ethernet-type":"LLDP",
                   "target-queue":0
               },{
                   "ethernet-type":"BDDP",
                   "target-queue":0
               },{
                   "ethernet-type":"0x1234",
                   "target-queue":1
               }]
           }
        }
      }

Where "target_queue" is queue number from 0 to 7 (7 is default queue),
"ethernet_type" is a type of a packet either in "0xFFFF" from or enum
name as defined in the "org.onlab.packet.EthType.EtherType" enum.

Change-Id: I0512ef653d90c36f00289014872170c1a8aa5204
diff --git a/protocols/openflow/api/BUILD b/protocols/openflow/api/BUILD
index bc5f55a..5e113b2 100644
--- a/protocols/openflow/api/BUILD
+++ b/protocols/openflow/api/BUILD
@@ -1,4 +1,4 @@
-COMPILE_DEPS = CORE_DEPS + NETTY + [
+COMPILE_DEPS = CORE_DEPS + NETTY + JACKSON + [
     "//core/common:onos-core-common",
     "@openflowj//jar",
     "@io_netty_netty_transport//jar",
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifier.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifier.java
new file mode 100644
index 0000000..6b746a0
--- /dev/null
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifier.java
@@ -0,0 +1,129 @@
+/*
+ * 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.openflow.controller;
+
+import org.onosproject.net.DeviceId;
+import java.util.Objects;
+
+/**
+ * Represents to OpenFlow messages classifier.
+ */
+public final class OpenFlowClassifier {
+
+    private final short ethernetType;
+    private final int idQueue;
+    private final DeviceId deviceId;
+
+    /**
+     * Builder of the OpenFlow classifier.
+     */
+    public static class Builder {
+        private Short ethernetType = 0;
+        private int idQueue;
+        private DeviceId deviceId;
+
+        /**
+         * Builder constructor for OpenFlow classifier.
+         *
+         * @param deviceId the device id
+         * @param idQueue  the queue id
+         */
+        public Builder(DeviceId deviceId, int idQueue) {
+            this.deviceId = deviceId;
+            this.idQueue = idQueue;
+        }
+
+        /**
+         * Sets the ethernet type for the OpenFlow classifier that will be built.
+         *
+         * @param ethernetType the ethernet type
+         * @return this builder
+         */
+        public Builder ethernetType(short ethernetType) {
+            this.ethernetType = ethernetType;
+            return this;
+        }
+
+        /**
+         * Builds the OpenFlow classifier from the accumulated parameters.
+         *
+         * @return OpenFlow classifier instance
+         */
+        public OpenFlowClassifier build() {
+            return new OpenFlowClassifier(this);
+        }
+    }
+
+    private OpenFlowClassifier(Builder builder) {
+        this.idQueue = builder.idQueue;
+        this.ethernetType = builder.ethernetType;
+        this.deviceId = builder.deviceId;
+    }
+
+    /**
+     * Gets the ethernet type matched by the classifier.
+     *
+     * @return matched packet ethernet type
+     */
+    public short ethernetType() {
+        return this.ethernetType;
+    }
+
+    /**
+     * Gets the id of source OpenFlow device matched by the classifier.
+     *
+     * @return connected device id
+     */
+    public DeviceId deviceId() {
+        return this.deviceId;
+    }
+
+    /**
+     * Gets the queue id targeted by the classifier.
+     *
+     * @return target queue id
+     */
+    public int idQueue() {
+        return this.idQueue;
+    }
+
+    /**
+     * Compares OpenFlow classifiers.
+     *
+     * @param o object that we want to compare to
+     * @return equality check result
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof OpenFlowClassifier)) {
+            return false;
+        }
+        OpenFlowClassifier classifier = (OpenFlowClassifier) o;
+        return this.ethernetType == classifier.ethernetType()
+               && this.idQueue == classifier.idQueue()
+               && this.deviceId.equals(classifier.deviceId());
+    }
+
+    /**
+     * Calculates hashCode of the OpenFlow Classifier object.
+     *
+     * @return hash of the OpenFlow Classifier
+     */
+    @Override
+    public int hashCode() {
+        return Objects.hash(deviceId, idQueue, ethernetType);
+    }
+}
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifierConfig.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifierConfig.java
new file mode 100644
index 0000000..8a44589
--- /dev/null
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifierConfig.java
@@ -0,0 +1,149 @@
+/*
+ * 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.openflow.controller;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Sets;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.Config;
+import org.onlab.packet.EthType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Configuration for classifiers.
+ */
+public class OpenFlowClassifierConfig extends Config<DeviceId> {
+    private static Logger log = LoggerFactory.getLogger(OpenFlowClassifierConfig.class);
+
+    public static final String TARGET_QUEUE = "target-queue";
+    public static final String ETHER_TYPE = "ethernet-type";
+
+    private static final String CONFIG_VALUE_ERROR = "Error parsing config value";
+    private static final String CLASSF_NULL_ERROR = "Classifier cannot be null";
+
+    private short etherValue(String etherType) throws IllegalArgumentException {
+        short etherTypeValue;
+        try {
+            if (etherType.startsWith("0x")) {
+                Integer e = Integer.valueOf(etherType.substring(2), 16);
+                if (e < 0 || e > 0xFFFF) {
+                    throw new IllegalArgumentException("EtherType value out of range");
+                }
+                etherTypeValue = e.shortValue();
+            } else {
+                etherTypeValue = EthType.EtherType.valueOf(etherType).ethType().toShort();
+            }
+        } catch (IllegalArgumentException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Failed to parse ethernet type string");
+        }
+        return etherTypeValue;
+    }
+
+    @Override
+    public boolean isValid() {
+        for (JsonNode node : array) {
+            if (!hasOnlyFields((ObjectNode) node, TARGET_QUEUE, ETHER_TYPE)) {
+                return false;
+            }
+
+            ObjectNode obj = (ObjectNode) node;
+
+            if (!(isString(obj, ETHER_TYPE, FieldPresence.MANDATORY) &&
+                  isIntegralNumber(obj, TARGET_QUEUE, FieldPresence.MANDATORY, 0, 7))) {
+                return false;
+            }
+
+            try {
+                etherValue(node.path(ETHER_TYPE).asText());
+            } catch (Exception e) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Retrieves all classifiers configured on this port.
+     *
+     * @return set of classifiers
+     */
+    public Set<OpenFlowClassifier> getClassifiers() {
+        Set<OpenFlowClassifier> classifiers = Sets.newHashSet();
+
+        for (JsonNode classfNode : array) {
+            DeviceId deviceId = this.subject();
+            short ethernetType = etherValue(classfNode.path(ETHER_TYPE).asText());
+            int idQueue = Integer.valueOf(classfNode.path(TARGET_QUEUE).asText());
+
+            OpenFlowClassifier classf =
+                new OpenFlowClassifier.Builder(deviceId, idQueue).ethernetType(ethernetType).build();
+            classifiers.add(classf);
+        }
+
+        return classifiers;
+    }
+
+    /**
+     * Adds a classifier to the config.
+     *
+     * @param classf classifier to add
+     */
+    public void addClassifier(OpenFlowClassifier classf) {
+        checkNotNull(classf, CLASSF_NULL_ERROR);
+        checkArgument(classf.deviceId().equals(this.subject()));
+
+        ObjectNode classfNode = array.addObject();
+
+        EthType.EtherType e = EthType.EtherType.lookup(classf.ethernetType());
+        if (e.equals(EthType.EtherType.UNKNOWN)) {
+            classfNode.put(ETHER_TYPE, String.format("0x%04x", classf.ethernetType()));
+        } else {
+            classfNode.put(ETHER_TYPE, e.name());
+        }
+        classfNode.put(TARGET_QUEUE, classf.idQueue());
+    }
+
+    /**
+     * Removes a classifier from the config.
+     *
+     * @param classf classifier to remove
+     */
+    public void removeClassifier(OpenFlowClassifier classf) {
+        checkNotNull(classf, CLASSF_NULL_ERROR);
+        checkArgument(classf.deviceId().equals(this.subject()));
+
+        Iterator<JsonNode> it = array.iterator();
+        while (it.hasNext()) {
+            JsonNode node = it.next();
+            if (etherValue(node.path(ETHER_TYPE).asText()) == classf.ethernetType()
+                && Integer.valueOf(node.path(TARGET_QUEUE).asText()) == classf.idQueue()) {
+                it.remove();
+                break;
+            }
+        }
+    }
+}
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifierListener.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifierListener.java
new file mode 100644
index 0000000..895ddd5
--- /dev/null
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowClassifierListener.java
@@ -0,0 +1,36 @@
+/*
+ * 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.openflow.controller;
+
+/**
+ * Notifies providers about OpenFlow Classifiers modifications.
+ */
+public interface OpenFlowClassifierListener {
+
+    /**
+     * Handle classifier add action.
+     *
+     * @param classifier the OpenFlow classifier
+     */
+    void handleClassifiersAdd(OpenFlowClassifier classifier);
+
+    /**
+     * Handle classifier remove action.
+     *
+     * @param classifier the OpenFlow classifier
+     */
+    void handleClassifiersRemove(OpenFlowClassifier classifier);
+}
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java
index e5d31596..3e153d7 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowController.java
@@ -152,4 +152,18 @@
      * @param dpid the switch to set the role for.
      */
     void setRole(Dpid dpid, RoleState role);
+
+    /**
+     * Remove OpenFlow classifier listener from runtime store of classifiers listener.
+     *
+     * @param listener the OpenFlow classifier to remove
+     */
+    void removeClassifierListener(OpenFlowClassifierListener listener);
+
+    /**
+     * Add OpenFlow classifier listener to runtime store of classifiers listener.
+     *
+     * @param listener the OpenFlow classifier listener
+     */
+    void addClassifierListener(OpenFlowClassifierListener listener);
 }
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowEvent.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowEvent.java
new file mode 100644
index 0000000..2aeaec1
--- /dev/null
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowEvent.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.openflow.controller;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Represent OpenFlow Classifiers events.
+ */
+public class OpenFlowEvent extends AbstractEvent<OpenFlowEvent.Type, OpenFlowClassifier> {
+
+    /**
+     * Enum of OpenFlow event type.
+     */
+    public enum Type {
+        /**
+         * Signifies that a new packet classifier has been added.
+         */
+        INSERT,
+        /**
+         * Signifies that a packet classifier has been removed.
+         */
+        REMOVE
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param type the OpenFlow event type
+     * @param subject the OpenFlow update data
+     */
+    public OpenFlowEvent(Type type, OpenFlowClassifier subject) {
+        super(type, subject);
+    }
+}
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowListener.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowListener.java
new file mode 100644
index 0000000..5f1a271
--- /dev/null
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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.openflow.controller;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Notifies providers about OpenFlow Classifiers events.
+ */
+public interface OpenFlowListener extends EventListener<OpenFlowEvent> {
+
+}
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowService.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowService.java
new file mode 100644
index 0000000..b702c23
--- /dev/null
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowService.java
@@ -0,0 +1,64 @@
+/*
+ * 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.openflow.controller;
+
+import java.util.Set;
+import org.onosproject.event.ListenerService;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Abstraction of an OpenFlow classifiers management.
+ */
+public interface OpenFlowService extends ListenerService<OpenFlowEvent, OpenFlowListener> {
+
+    /**
+     * Adds the OpenFlow classifier to the information base.
+     *
+     * @param classifier the OpenFlow classifier
+     */
+    void add(OpenFlowClassifier classifier);
+
+    /**
+     * Removes the OpenFlow classifier from the information base.
+     *
+     * @param classifier classifier to remove
+     */
+    void remove(OpenFlowClassifier classifier);
+
+    /**
+     * Gets all OpenFlow classifiers in the system.
+     *
+     * @return set of OpenFlow classifiers
+     */
+    Set<OpenFlowClassifier> getClassifiers();
+
+    /**
+     * Obtains OpenFlow classifiers in the system by device id.
+     *
+     * @param deviceId the device id
+     * @return set of OpenFlow classifiers
+     */
+    Set<OpenFlowClassifier> getClassifiersByDeviceId(DeviceId deviceId);
+
+    /**
+     * Obtains OpenFlow classifiers in the system by device id and number of queue.
+     *
+     * @param deviceId the device id
+     * @param idQueue the queue id
+     * @return set of OpenFlow classifiers
+     */
+    Set<OpenFlowClassifier> getClassifiersByDeviceIdAndQueue(DeviceId deviceId, int idQueue);
+}
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSession.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSession.java
index c380322..1677e5e 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSession.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowSession.java
@@ -60,5 +60,17 @@
      */
     CharSequence sessionInfo();
 
+    /**
+     * Add classifier to runtime store of classifiers.
+     *
+     * @param classifier the OpenFlow classifier to add
+     */
+    void addClassifier(OpenFlowClassifier classifier);
 
+    /**
+     * Remove classifier from runtime store of classifiers.
+     *
+     * @param classifier the OpenFlow classifier to remove
+     */
+    void removeClassifier(OpenFlowClassifier classifier);
 }
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
index 0ba3bd9..8431068 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.onosproject.openflow.controller.driver;
 
 import com.google.common.base.MoreObjects;
@@ -23,6 +22,8 @@
 import org.onosproject.net.Device;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.OpenFlowClassifier;
+import org.onosproject.openflow.controller.OpenFlowClassifierListener;
 import org.onosproject.openflow.controller.OpenFlowSession;
 import org.onosproject.openflow.controller.RoleState;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
@@ -98,6 +99,8 @@
 
     private OFMeterFeaturesStatsReply meterfeatures;
 
+    protected OpenFlowClassifierListener classifierListener = new InternalClassifierListener();
+
     // messagesPendingMastership is used as synchronization variable for
     // all mastership related changes. In this block, mastership (including
     // role update) will have either occurred or not.
@@ -301,7 +304,11 @@
 
     @Override
     public final boolean connectSwitch() {
-        return this.agent.addConnectedSwitch(dpid, this);
+        boolean status = this.agent.addConnectedSwitch(dpid, this);
+        if (status) {
+            this.agent.addClassifierListener(classifierListener);
+        }
+        return status;
     }
 
     @Override
@@ -339,6 +346,7 @@
     @Override
     public final void removeConnectedSwitch() {
         this.agent.removeConnectedSwitch(dpid);
+        this.agent.removeClassifierListener(classifierListener);
     }
 
     @Override
@@ -566,4 +574,17 @@
                 .add("dpid", dpid)
                 .toString();
     }
+
+    private class InternalClassifierListener implements OpenFlowClassifierListener {
+
+        @Override
+        public void handleClassifiersAdd(OpenFlowClassifier classifier) {
+            channel.addClassifier(classifier);
+        }
+
+        @Override
+        public void handleClassifiersRemove(OpenFlowClassifier classifier) {
+            channel.removeClassifier(classifier);
+        }
+    }
 }
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java
index 37c43f3..4451b19 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/driver/OpenFlowAgent.java
@@ -16,6 +16,7 @@
 package org.onosproject.openflow.controller.driver;
 
 import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.OpenFlowClassifierListener;
 import org.onosproject.openflow.controller.OpenFlowSwitch;
 import org.onosproject.openflow.controller.RoleState;
 import org.projectfloodlight.openflow.protocol.OFMessage;
@@ -109,4 +110,18 @@
      * @param response role reply from the switch
      */
     void returnRoleReply(Dpid dpid, RoleState requested, RoleState response);
+
+    /**
+     * Add OpenFlow classifier listener.
+     *
+     * @param listener the OpenFlow classifier listener
+     */
+    void addClassifierListener(OpenFlowClassifierListener listener);
+
+    /**
+     * Remove OpenFlow classifier listener.
+     *
+     * @param listener the OpenFlow classifier listener
+     */
+    void removeClassifierListener(OpenFlowClassifierListener listener);
 }
diff --git a/protocols/openflow/api/src/test/java/org/onosproject/openflow/controller/OpenflowControllerAdapter.java b/protocols/openflow/api/src/test/java/org/onosproject/openflow/controller/OpenflowControllerAdapter.java
index a3b8e5c..5056840 100644
--- a/protocols/openflow/api/src/test/java/org/onosproject/openflow/controller/OpenflowControllerAdapter.java
+++ b/protocols/openflow/api/src/test/java/org/onosproject/openflow/controller/OpenflowControllerAdapter.java
@@ -103,4 +103,12 @@
     @Override
     public void removeEventListener(OpenFlowEventListener listener) {
     }
+
+    @Override
+    public void removeClassifierListener(OpenFlowClassifierListener listener) {
+    }
+
+    @Override
+    public void addClassifierListener(OpenFlowClassifierListener listener) {
+    }
 }