[CORD-545] Adds QoS Index support in ONOS core

Change-Id: If7649bdf70f5a796466b8efc5798dc3346ea94a0
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 f21bb7f..01848a7 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
@@ -52,6 +52,7 @@
         OFDPA_SET_MPLS_TYPE(65),
         OFDPA_SET_OVID(66),
         OFDPA_SET_MPLS_L2_PORT(67),
+        OFDPA_SET_QOS_INDEX(68),
         NICIRA_TUN_GPE_NP(111),
         NICIRA_SET_NSH_SPI(113),
         NICIRA_SET_NSH_SI(114),
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionTreatmentInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionTreatmentInterpreter.java
index c449702..067e294 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionTreatmentInterpreter.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3ExtensionTreatmentInterpreter.java
@@ -30,8 +30,10 @@
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaMplsL2Port;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaMplsType;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaOvid;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaQosIndex;
 import org.projectfloodlight.openflow.types.U16;
 import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U8;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -54,6 +56,9 @@
         } else if (extensionTreatmentType.equals(
                 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.type())) {
             return true;
+        } else if (extensionTreatmentType.equals(
+                ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type())) {
+            return true;
         }
         return false;
     }
@@ -86,6 +91,18 @@
             }
             throw new UnsupportedOperationException(
                     "Unexpected ExtensionTreatment: " + extensionTreatment.toString());
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type())) {
+            Integer qosIndex = ((Ofdpa3SetQosIndex) extensionTreatment).qosIndex();
+            /*
+             * Qos index is a single byte [0...255]
+             */
+            if (qosIndex >= 0 && qosIndex <= 255) {
+                return factory.actions().setField(
+                        factory.oxms().ofdpaQosIndex(U8.ofRaw((byte) (qosIndex & 0xFF)))
+                );
+            }
+            throw new UnsupportedOperationException(
+                    "Unexpected ExtensionTreatment: " + extensionTreatment.toString());
         }
         throw new UnsupportedOperationException(
                 "Unexpected ExtensionTreatment: " + extensionTreatment.toString());
@@ -113,6 +130,14 @@
                             (mplsL2Port >= 0x00020000 && mplsL2Port <= 0x0002FFFF)) {
                         return new Ofdpa3SetMplsL2Port(mplsL2Port);
                     }
+                    break;
+                case OFDPA_QOS_INDEX:
+                    OFOxmOfdpaQosIndex qosindex = ((OFOxmOfdpaQosIndex) oxm);
+                    Integer qosIndex = (int) qosindex.getValue().getRaw();
+                    if (qosIndex >= 0 && qosIndex <= 255) {
+                        return new Ofdpa3SetQosIndex(qosIndex);
+                    }
+                    break;
                 default:
                     throw new UnsupportedOperationException(
                             "Driver does not support extension type " + oxm.getMatchField().id);
@@ -130,6 +155,8 @@
             return new Ofdpa3SetOvid();
         } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.type())) {
             return new Ofdpa3SetMplsL2Port();
+        } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type())) {
+            return new Ofdpa3SetQosIndex();
         }
         throw new UnsupportedOperationException(
                 "Driver does not support extension type " + type.toString());
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3SetQosIndex.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3SetQosIndex.java
new file mode 100644
index 0000000..a6a62d6
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3SetQosIndex.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016-present 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.driver.extensions;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import java.util.Objects;
+
+/**
+ * OFDPA set Qos Index extension instruction.
+ */
+public class Ofdpa3SetQosIndex extends AbstractExtension implements ExtensionTreatment {
+    /**
+     * Byte storing the Qos index.
+     */
+    private int qosIndex;
+
+    private static final KryoNamespace APPKRYO = new KryoNamespace.Builder()
+            .build();
+
+    /**
+     * Constructs a new set Qos index instruction.
+     */
+    protected Ofdpa3SetQosIndex() {
+        qosIndex = 0x00;
+    }
+
+    /**
+     * Constructs a new set Qos index instruction with a given int.
+     *
+     * @param qosindex Qos index as integer
+     */
+    public Ofdpa3SetQosIndex(int qosindex) {
+        qosIndex = qosindex;
+    }
+
+    /**
+     * Gets the Qos index as int.
+     *
+     * @return the Qos index as int.
+     */
+    public int qosIndex() {
+        return qosIndex;
+    }
+
+    @Override
+    public ExtensionTreatmentType type() {
+        return ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type();
+    }
+
+    @Override
+    public void deserialize(byte[] data) {
+        qosIndex = APPKRYO.deserialize(data);
+    }
+
+    @Override
+    public byte[] serialize() {
+        return APPKRYO.serialize(qosIndex);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(qosIndex);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof Ofdpa3SetQosIndex) {
+            Ofdpa3SetQosIndex that = (Ofdpa3SetQosIndex) obj;
+            return Objects.equals(qosIndex, that.qosIndex);
+
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("qosIndex", qosIndex)
+                .toString();
+    }
+}
\ No newline at end of file
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/Ofdpa3SetQosIndexCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/Ofdpa3SetQosIndexCodec.java
new file mode 100644
index 0000000..740c7d6
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/Ofdpa3SetQosIndexCodec.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present 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.driver.extensions.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.driver.extensions.Ofdpa3SetQosIndex;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for Ofdpa set qos index class.
+ */
+public class Ofdpa3SetQosIndexCodec extends JsonCodec<Ofdpa3SetQosIndex>  {
+
+    private static final String QOS_INDEX = "qosIndex";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in Ofdpa3SetQosIndex";
+    private static final String MISSING_QOS_INDEX_TYPE_MESSAGE = "qosIndex cannot be null";
+
+    @Override
+    public ObjectNode encode(Ofdpa3SetQosIndex qosIndex, CodecContext context) {
+        checkNotNull(qosIndex, MISSING_QOS_INDEX_TYPE_MESSAGE);
+        return context.mapper().createObjectNode()
+                .put(QOS_INDEX, qosIndex.qosIndex());
+    }
+
+    @Override
+    public Ofdpa3SetQosIndex decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse ofdpa qos index
+        int qosIndex = (int) nullIsIllegal(json.get(QOS_INDEX),
+                QOS_INDEX + MISSING_MEMBER_MESSAGE).asInt();
+        return new Ofdpa3SetQosIndex(qosIndex);
+    }
+}
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
index 5b6c2f3..2b042e6 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
@@ -582,6 +582,7 @@
         case OFDPA_MPLS_TYPE:
         case OFDPA_OVID:
         case OFDPA_MPLS_L2_PORT:
+        case OFDPA_QOS_INDEX:
             if (treatmentInterpreter != null) {
                 try {
                     builder.extension(treatmentInterpreter.mapAction(action), deviceId);