Implemented the extension framework for selectors.

Change-Id: I577900141889fc70ca54e96cd5d54cfd5194b05d
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionSelectorResolver.java b/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionSelectorResolver.java
new file mode 100644
index 0000000..d45dd53
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionSelectorResolver.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.behaviour;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+
+/**
+ * Provides access to the extension selectors implemented by this driver.
+ */
+@Beta
+public interface ExtensionSelectorResolver extends HandlerBehaviour {
+
+    /**
+     * Gets an extension selector instance of the specified type, if supported
+     * by the driver.
+     *
+     * @param type type of extension to get
+     * @return extension selector
+     * @throws UnsupportedOperationException if the extension type is not
+     * supported by this driver
+     */
+    ExtensionSelector getExtensionSelector(ExtensionSelectorType type);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/AbstractExtension.java
similarity index 90%
rename from core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionTreatment.java
rename to core/api/src/main/java/org/onosproject/net/flow/AbstractExtension.java
index ac7c771..b48d69c 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/AbstractExtension.java
@@ -14,22 +14,25 @@
  * limitations under the License.
  */
 
-package org.onosproject.net.flow.instructions;
+package org.onosproject.net.flow;
+
+import org.onosproject.net.flow.instructions.ExtensionPropertyException;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
- * Abstract implementation of the set/get property methods of ExtensionInstruction.
+ * Abstract implementation of the set/get property methods of Extension.
  */
-public abstract class AbstractExtensionTreatment implements ExtensionTreatment {
+public abstract class AbstractExtension implements Extension {
 
     private static final String INVALID_KEY = "Invalid property key: ";
     private static final String INVALID_TYPE = "Given type does not match field type: ";
 
     @Override
-    public <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException {
+    public <T> void setPropertyValue(String key, T value) throws
+            ExtensionPropertyException {
         Class<?> clazz = this.getClass();
         try {
             Field field = clazz.getDeclaredField(key);
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
index d3c2449..0525d8f 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
@@ -15,14 +15,8 @@
  */
 package org.onosproject.net.flow;
 
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
-
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip6Address;
 import org.onlab.packet.IpPrefix;
@@ -30,12 +24,19 @@
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
 
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableSet;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
 
 /**
  * Default traffic selector implementation.
@@ -379,6 +380,12 @@
         }
 
         @Override
+        public TrafficSelector.Builder extension(ExtensionSelector extensionSelector,
+                                                 DeviceId deviceId) {
+            return add(Criteria.extension(extensionSelector, deviceId));
+        }
+
+        @Override
         public TrafficSelector build() {
             return new DefaultTrafficSelector(ImmutableSet.copyOf(selector.values()));
         }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/Extension.java b/core/api/src/main/java/org/onosproject/net/flow/Extension.java
new file mode 100644
index 0000000..1d61542
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/flow/Extension.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.flow;
+
+import org.onosproject.net.flow.instructions.ExtensionPropertyException;
+
+import java.util.List;
+
+/**
+ * An extension to the northbound APIs.
+ */
+public interface Extension {
+
+    /**
+     * Sets a property on the extension.
+     *
+     * @param key property key
+     * @param value value to set for the given key
+     * @param <T> class of the value
+     * @throws ExtensionPropertyException if the given key is not a valid
+     * property on this extension
+     */
+    <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException;
+
+    /**
+     * Gets a property value of an extension.
+     *
+     * @param key property key
+     * @param <T> class of the value
+     * @return value of the property
+     * @throws ExtensionPropertyException if the given key is not a valid
+     * property on this extension
+     */
+    <T> T getPropertyValue(String key) throws ExtensionPropertyException;
+
+    /**
+     * Gets a list of all properties on the extension.
+     *
+     * @return list of properties
+     */
+    List<String> getProperties();
+
+    /**
+     * Serialize the extension to a byte array.
+     *
+     * @return byte array
+     */
+    byte[] serialize();
+
+    /**
+     * Deserialize the extension from a byte array. The properties
+     * of this object will be overwritten with the data in the byte array.
+     *
+     * @param data input byte array
+     */
+    void deserialize(byte[] data);
+}
diff --git a/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java b/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
index b92281f..0d055ad 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java
@@ -15,8 +15,6 @@
  */
 package org.onosproject.net.flow;
 
-import java.util.Set;
-
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip6Address;
 import org.onlab.packet.IpPrefix;
@@ -24,8 +22,12 @@
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+
+import java.util.Set;
 
 /**
  * Abstraction of a slice of network traffic.
@@ -427,6 +429,15 @@
         Builder matchArpOp(int arpOp);
 
         /**
+         * Uses an extension selector.
+         *
+         * @param extensionSelector extension selector
+         * @param deviceId device ID
+         * @return a selection builder
+         */
+        Builder extension(ExtensionSelector extensionSelector, DeviceId deviceId);
+
+        /**
          * Builds an immutable traffic selector.
          *
          * @return traffic selector
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
index a28a4ab..dd31ad4 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/Criteria.java
@@ -23,6 +23,7 @@
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.IndexedLambda;
 import org.onosproject.net.Lambda;
 import org.onosproject.net.OchSignal;
@@ -579,6 +580,23 @@
         return new ArpOpCriterion(arpOp, Type.ARP_OP);
     }
 
+    /**
+     * Creates an extension criterion for the specified extension selector.
+     *
+     * @param extensionSelector extension selector
+     * @param deviceId device ID
+     * @return match criterion
+     */
+    public static Criterion extension(ExtensionSelector extensionSelector,
+                                      DeviceId deviceId) {
+        return new ExtensionCriterion(extensionSelector, deviceId);
+    }
+
+    /**
+     * Creates a dummy criterion.
+     *
+     * @return match criterion
+     */
     public static Criterion dummy() {
         return new DummyCriterion();
     }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java
index 2666524..17557b9 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/Criterion.java
@@ -177,6 +177,9 @@
         /** ODU (Optical channel Data Unit) signal type. */
         ODU_SIGTYPE,
 
+        /** Extension criterion. */
+        EXTENSION,
+
         /** An empty criterion. */
         DUMMY
     }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionCriterion.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionCriterion.java
new file mode 100644
index 0000000..646b418
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionCriterion.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.flow.criteria;
+
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Criterion for implementing selector extensions.
+ */
+public class ExtensionCriterion implements Criterion {
+
+    private final ExtensionSelector extensionSelector;
+    private final DeviceId deviceId;
+
+    /**
+     * Constructor.
+     *
+     * @param extensionSelector extension selector
+     */
+    public ExtensionCriterion(ExtensionSelector extensionSelector, DeviceId deviceId) {
+        this.extensionSelector = extensionSelector;
+        this.deviceId = deviceId;
+    }
+
+    /**
+     * Returns the extension selector.
+     *
+     * @return extension selector
+     */
+    public ExtensionSelector extensionSelector() {
+        return extensionSelector;
+    }
+
+    /**
+     * Returns the device ID.
+     *
+     * @return device ID
+     */
+    public DeviceId deviceId() {
+        return deviceId;
+    }
+
+    @Override
+    public Type type() {
+        return Type.EXTENSION;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(type().toString())
+                .add("extensionSelector", extensionSelector.toString())
+                .add("deviceId", deviceId)
+                .toString();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type().ordinal(), extensionSelector, deviceId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ExtensionCriterion) {
+            ExtensionCriterion that = (ExtensionCriterion) obj;
+            return Objects.equals(extensionSelector, that.extensionSelector) &&
+                    Objects.equals(deviceId, that.deviceId) &&
+                    Objects.equals(this.type(), that.type());
+        }
+        return false;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelector.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelector.java
new file mode 100644
index 0000000..d3cebb3
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelector.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.flow.criteria;
+
+import org.onosproject.net.flow.Extension;
+
+/**
+ * An extension for the selector API.
+ */
+public interface ExtensionSelector extends Extension {
+
+    /**
+     * Gets the type of the extension selector.
+     *
+     * @return type
+     */
+    ExtensionSelectorType type();
+}
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java
new file mode 100644
index 0000000..982e5b1
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.flow.criteria;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Type of selector extensions.
+ */
+@Beta
+public class ExtensionSelectorType {
+
+    /**
+     * A list of well-known named extension selector type codes.
+     * These numbers have no impact on the actual OF type id.
+     */
+    public enum ExtensionSelectorTypes {
+        PLACEHOLDER(0); // TODO remove when actual extensions are added
+
+        private ExtensionSelectorType type;
+
+        /**
+         * Creates a new named extension selector type.
+         *
+         * @param type type code
+         */
+        ExtensionSelectorTypes(int type) {
+            this.type = new ExtensionSelectorType(type);
+        }
+
+        /**
+         * Gets the extension type object for this named type code.
+         *
+         * @return extension type object
+         */
+        public ExtensionSelectorType type() {
+            return type;
+        }
+    }
+
+    private final int type;
+
+    /**
+     * Creates an extension type with the given int type code.
+     *
+     * @param type type code
+     */
+    public ExtensionSelectorType(int type) {
+        this.type = type;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ExtensionSelectorType) {
+            final ExtensionSelectorType that = (ExtensionSelectorType) obj;
+            return this.type == that.type;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(ExtensionSelectorType.class)
+                .add("type", type)
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatment.java
index 0e8885e..35a2d12 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatment.java
@@ -16,12 +16,12 @@
 
 package org.onosproject.net.flow.instructions;
 
-import java.util.List;
+import org.onosproject.net.flow.Extension;
 
 /**
- * An extensible instruction type.
+ * An extenstion for the treatment API.
  */
-public interface ExtensionTreatment {
+public interface ExtensionTreatment extends Extension {
 
     /**
      * Gets the type of the extension instruction.
@@ -30,49 +30,4 @@
      */
     ExtensionTreatmentType type();
 
-    /**
-     * Sets a property on the extension instruction.
-     *
-     * @param key property key
-     * @param value value to set for the given key
-     * @param <T> class of the value
-     * @throws ExtensionPropertyException if the given key is not a valid
-     * property on this extension instruction
-     */
-    <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException;
-
-    /**
-     * Gets a property value of an extension instruction.
-     *
-     * @param key property key
-     * @param <T> class of the value
-     * @return value of the property
-     * @throws ExtensionPropertyException if the given key is not a valid
-     * property on this extension instruction
-     */
-    <T> T getPropertyValue(String key) throws ExtensionPropertyException;
-
-    /**
-     * Gets a list of all properties on the extension instruction.
-     *
-     * @return list of properties
-     */
-    List<String> getProperties();
-
-    /**
-     * Serialize the extension instruction to a byte array.
-     *
-     * @return byte array
-     */
-    byte[] serialize();
-
-    /**
-     * Deserialize the extension instruction from a byte array. The properties
-     * of this object will be overwritten with the data in the byte array.
-     *
-     * @param data input byte array
-     */
-    void deserialize(byte[] data);
-
-
 }
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
index 821c1d9..9715fc0 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
@@ -22,7 +22,7 @@
 import java.util.Objects;
 
 /**
- * Type of extension instructions.
+ * Type of treatment extensions.
  */
 @Beta
 public final class ExtensionTreatmentType {