[ONOS-4258] Initial implementation of supporting extension in REST

- Support Nicira extension

Change-Id: I62bf4417e43459727ce7d4b1ac929c6cf0b7826f
diff --git a/core/api/src/main/java/org/onosproject/codec/ExtensionSelectorCodec.java b/core/api/src/main/java/org/onosproject/codec/ExtensionSelectorCodec.java
new file mode 100644
index 0000000..fc51216
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/codec/ExtensionSelectorCodec.java
@@ -0,0 +1,48 @@
+/*
+ * 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.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+
+/**
+ * Interface for encode and decode extension selector.
+ */
+public interface ExtensionSelectorCodec extends HandlerBehaviour {
+
+    /**
+     * Encodes an extension selector to an JSON object.
+     *
+     * @param extensionSelector extension selector
+     * @param  context encoding context
+     * @return JSON object
+     */
+    default ObjectNode encode(ExtensionSelector extensionSelector, CodecContext context) {
+        return null;
+    }
+
+    /**
+     * Decodes an JSON object to an extension selector.
+     *
+     * @param objectNode JSON object
+     * @param  context decoding context
+     * @return extension selector
+     */
+    default ExtensionSelector decode(ObjectNode objectNode, CodecContext context) {
+        return null;
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/codec/ExtensionTreatmentCodec.java b/core/api/src/main/java/org/onosproject/codec/ExtensionTreatmentCodec.java
new file mode 100644
index 0000000..e33258b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/codec/ExtensionTreatmentCodec.java
@@ -0,0 +1,48 @@
+/*
+ * 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.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+
+/**
+ * Interface for encode and decode extension treatment.
+ */
+public interface ExtensionTreatmentCodec extends HandlerBehaviour {
+
+    /**
+     * Encodes an extension treatment to an JSON object.
+     *
+     * @param extensionTreatment extension treatment
+     * @param  context encoding context
+     * @return JSON object
+     */
+    default ObjectNode encode(ExtensionTreatment extensionTreatment, CodecContext context) {
+        return null;
+    }
+
+    /**
+     * Decodes an JSON object to an extension treatment.
+     *
+     * @param objectNode JSON object
+     * @param  context decoding context
+     * @return extension treatment
+     */
+    default ExtensionTreatment decode(ObjectNode objectNode, CodecContext context) {
+        return null;
+    }
+}
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 cf2400c..df9789e 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
@@ -79,6 +79,15 @@
         this.type = type;
     }
 
+    /**
+     * Returns extension treatment type.
+     *
+     * @return extension treatment type
+     */
+    public int type() {
+        return type;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(type);
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
index 03dd496..b70a684 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
@@ -15,20 +15,28 @@
  */
 package org.onosproject.codec.impl;
 
+import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
 import org.onlab.util.HexString;
+import org.onosproject.codec.ExtensionTreatmentCodec;
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.GridType;
 import org.onosproject.net.OchSignal;
 import org.onosproject.net.OduSignalId;
 import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
@@ -37,13 +45,16 @@
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
 import org.onosproject.net.meter.MeterId;
+import org.slf4j.Logger;
 
 import static org.onlab.util.Tools.nullIsIllegal;
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
  * Decoding portion of the instruction codec.
  */
 public final class DecodeInstructionCodecHelper {
+    protected static final Logger log = getLogger(DecodeInstructionCodecHelper.class);
     private final ObjectNode json;
 
     /**
@@ -227,6 +238,45 @@
     }
 
     /**
+     * Decodes a extension instruction.
+     *
+     * @return extension treatment
+     */
+    private Instruction decodeExtension() {
+        ObjectNode node = (ObjectNode) json.get(InstructionCodec.EXTENSION);
+        if (node != null) {
+            DeviceId deviceId = getDeviceId();
+
+            ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+            DeviceService deviceService = serviceDirectory.get(DeviceService.class);
+            Device device = deviceService.getDevice(deviceId);
+
+            if (device.is(ExtensionTreatmentCodec.class)) {
+                ExtensionTreatmentCodec treatmentCodec = device.as(ExtensionTreatmentCodec.class);
+                ExtensionTreatment treatment = treatmentCodec.decode(node, null);
+                return Instructions.extension(treatment, deviceId);
+            } else {
+                log.warn("There is no codec to decode extension for device {}", deviceId.toString());
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns device identifier.
+     *
+     * @return device identifier
+     * @throws IllegalArgumentException if the JSON is invalid
+     */
+    private DeviceId getDeviceId() {
+        JsonNode deviceIdNode = json.get(InstructionCodec.DEVICE_ID);
+        if (deviceIdNode != null) {
+            return DeviceId.deviceId(deviceIdNode.asText());
+        }
+        throw new IllegalArgumentException("Empty device identifier");
+    }
+
+    /**
      * Extracts port number of the given json node.
      *
      * @param jsonNode json node
@@ -290,6 +340,8 @@
             return decodeL3();
         } else if (type.equals(Instruction.Type.L4MODIFICATION.name())) {
             return decodeL4();
+        } else if (type.equals(Instruction.Type.EXTENSION.name())) {
+            return decodeExtension();
         }
         throw new IllegalArgumentException("Instruction type "
                 + type + " is not supported");
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java b/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
index b108f7e..3d1ed2f 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
@@ -16,10 +16,16 @@
 package org.onosproject.codec.impl;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
 import org.onlab.util.HexString;
 import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.ExtensionTreatmentCodec;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.OchSignal;
 import org.onosproject.net.OduSignalId;
+import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
@@ -28,13 +34,14 @@
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
 import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
  * JSON encoding of Instructions.
  */
 public final class EncodeInstructionCodecHelper {
-    protected static final Logger log = LoggerFactory.getLogger(EncodeInstructionCodecHelper.class);
+    protected static final Logger log = getLogger(EncodeInstructionCodecHelper.class);
     private final Instruction instruction;
     private final CodecContext context;
 
@@ -219,14 +226,29 @@
         }
     }
 
+
     /**
-     * Encode a extension instruction.
+     * Encodes a extension instruction.
      *
      * @param result json node that the instruction attributes are added to
      */
     private void encodeExtension(ObjectNode result) {
-        // TODO Support extension in REST API
-        log.info("Cannot convert instruction type of EXTENSION");
+        final Instructions.ExtensionInstructionWrapper extensionInstruction =
+                (Instructions.ExtensionInstructionWrapper) instruction;
+
+        DeviceId deviceId = extensionInstruction.deviceId();
+
+        ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+        DeviceService deviceService = serviceDirectory.get(DeviceService.class);
+        Device device = deviceService.getDevice(deviceId);
+
+        if (device.is(ExtensionTreatmentCodec.class)) {
+            ExtensionTreatmentCodec treatmentCodec = device.as(ExtensionTreatmentCodec.class);
+            ObjectNode node = treatmentCodec.encode(extensionInstruction.extensionInstruction(), context);
+            result.set(InstructionCodec.EXTENSION, node);
+        } else {
+            log.warn("There is no codec to encode extension for device {}", deviceId.toString());
+        }
     }
 
     /**
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
index 3616e54..da41e25 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
@@ -57,6 +57,8 @@
     protected static final String TRIBUTARY_PORT_NUMBER = "tributaryPortNumber";
     protected static final String TRIBUTARY_SLOT_LEN = "tributarySlotLength";
     protected static final String TRIBUTARY_SLOT_BITMAP = "tributarySlotBitmap";
+    protected static final String EXTENSION = "extension";
+    protected static final String DEVICE_ID = "deviceId";
 
     protected static final String MISSING_MEMBER_MESSAGE =
             " member is required in Instruction";
diff --git a/drivers/default/src/main/java/org/onosproject/driver/DefaultCodecRegister.java b/drivers/default/src/main/java/org/onosproject/driver/DefaultCodecRegister.java
new file mode 100644
index 0000000..b37bb62
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/DefaultCodecRegister.java
@@ -0,0 +1,84 @@
+/*
+ * 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;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.codec.CodecService;
+import org.onosproject.driver.extensions.MoveExtensionTreatment;
+import org.onosproject.driver.extensions.NiciraMatchNshSi;
+import org.onosproject.driver.extensions.NiciraMatchNshSpi;
+import org.onosproject.driver.extensions.NiciraResubmit;
+import org.onosproject.driver.extensions.NiciraResubmitTable;
+import org.onosproject.driver.extensions.NiciraSetNshContextHeader;
+import org.onosproject.driver.extensions.NiciraSetNshSi;
+import org.onosproject.driver.extensions.NiciraSetNshSpi;
+import org.onosproject.driver.extensions.NiciraSetTunnelDst;
+import org.onosproject.driver.extensions.codec.MoveExtensionTreatmentCodec;
+import org.onosproject.driver.extensions.codec.NiciraMatchNshSiCodec;
+import org.onosproject.driver.extensions.codec.NiciraMatchNshSpiCodec;
+import org.onosproject.driver.extensions.codec.NiciraResubmitCodec;
+import org.onosproject.driver.extensions.codec.NiciraResubmitTableCodec;
+import org.onosproject.driver.extensions.codec.NiciraSetNshContextHeaderCodec;
+import org.onosproject.driver.extensions.codec.NiciraSetNshSiCodec;
+import org.onosproject.driver.extensions.codec.NiciraSetNshSpiCodec;
+import org.onosproject.driver.extensions.codec.NiciraSetTunnelDstCodec;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Codec register for default drivers.
+ */
+@Component(immediate = true)
+public class DefaultCodecRegister {
+
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CodecService codecService;
+
+    @Activate
+    public void activate() {
+        codecService.registerCodec(MoveExtensionTreatment.class, new MoveExtensionTreatmentCodec());
+        codecService.registerCodec(NiciraMatchNshSi.class, new NiciraMatchNshSiCodec());
+        codecService.registerCodec(NiciraMatchNshSpi.class, new NiciraMatchNshSpiCodec());
+        codecService.registerCodec(NiciraResubmit.class, new NiciraResubmitCodec());
+        codecService.registerCodec(NiciraResubmitTable.class, new NiciraResubmitTableCodec());
+        codecService.registerCodec(NiciraSetNshSi.class, new NiciraSetNshSiCodec());
+        codecService.registerCodec(NiciraSetNshSpi.class, new NiciraSetNshSpiCodec());
+        codecService.registerCodec(NiciraSetTunnelDst.class, new NiciraSetTunnelDstCodec());
+        codecService.registerCodec(NiciraSetNshContextHeader.class, new NiciraSetNshContextHeaderCodec());
+        log.info("Registered default driver codecs.");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        codecService.unregisterCodec(MoveExtensionTreatment.class);
+        codecService.unregisterCodec(NiciraMatchNshSi.class);
+        codecService.unregisterCodec(NiciraMatchNshSpi.class);
+        codecService.unregisterCodec(NiciraResubmit.class);
+        codecService.unregisterCodec(NiciraResubmitTable.class);
+        codecService.unregisterCodec(NiciraSetNshSi.class);
+        codecService.unregisterCodec(NiciraSetNshSpi.class);
+        codecService.unregisterCodec(NiciraSetTunnelDst.class);
+        codecService.unregisterCodec(NiciraSetNshContextHeader.class);
+        log.info("Unregistered default driver codecs.");
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java
index 55fcda0..57f0a67 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java
@@ -16,6 +16,8 @@
 
 package org.onosproject.driver.extensions;
 
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
 import org.onosproject.net.behaviour.ExtensionSelectorResolver;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
 import org.onosproject.net.flow.criteria.ExtensionSelector;
@@ -99,4 +101,16 @@
         }
         return null;
     }
+
+    @Override
+    public ObjectNode encode(ExtensionSelector extensionSelector, CodecContext context) {
+        // TODO
+        return null;
+    }
+
+    @Override
+    public ExtensionSelector decode(ObjectNode json, CodecContext context) {
+        // TODO
+        return null;
+    }
 }
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
index ea49e1a..f30680d 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
@@ -16,7 +16,9 @@
 
 package org.onosproject.driver.extensions;
 
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.onlab.packet.Ip4Address;
+import org.onosproject.codec.CodecContext;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
@@ -35,6 +37,9 @@
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst;
 import org.projectfloodlight.openflow.types.IPv4Address;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
 /**
  * Interpreter for Nicira OpenFlow treatment extensions.
  */
@@ -50,6 +55,18 @@
     private static final int SUB_TYPE_RESUBMIT = 1;
     private static final int SUB_TYPE_MOVE = 6;
 
+    private static final String TUNNEL_DST = "tunnelDst";
+    private static final String RESUBMIT = "resubmit";
+    private static final String RESUBMIT_TABLE = "resubmitTable";
+    private static final String NICIRA_NSH_SPI = "niciraNshSpi";
+    private static final String NICIRA_NSH_SI = "niciraNshSi";
+    private static final String NICIRA_NSH_CH = "niciraNshCh";
+    private static final String NICIRA_MOVE = "niciraMove";
+
+    private static final String TYPE = "type";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraExtensionTreatmentInterpreter";
+
     @Override
     public boolean supported(ExtensionTreatmentType extensionTreatmentType) {
         if (extensionTreatmentType.equals(
@@ -250,4 +267,106 @@
         throw new UnsupportedOperationException(
                 "Driver does not support extension type " + type.toString());
     }
+
+    @Override
+    public ObjectNode encode(ExtensionTreatment extensionTreatment, CodecContext context) {
+        checkNotNull(extensionTreatment, "Extension treatment cannot be null");
+        ExtensionTreatmentType type = extensionTreatment.type();
+        ObjectNode root = context.mapper().createObjectNode();
+
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type())) {
+            NiciraSetTunnelDst tunnelDst = (NiciraSetTunnelDst) extensionTreatment;
+            root.set(TUNNEL_DST, context.codec(NiciraSetTunnelDst.class).encode(tunnelDst, context));
+        }
+
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) {
+            NiciraResubmit resubmit = (NiciraResubmit) extensionTreatment;
+            root.set(RESUBMIT, context.codec(NiciraResubmit.class).encode(resubmit, context));
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) {
+            NiciraResubmitTable resubmitTable = (NiciraResubmitTable) extensionTreatment;
+            root.set(RESUBMIT_TABLE, context.codec(NiciraResubmitTable.class).encode(resubmitTable, context));
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) {
+            NiciraSetNshSpi niciraNshSpi = (NiciraSetNshSpi) extensionTreatment;
+            root.set(NICIRA_NSH_SPI, context.codec(NiciraSetNshSpi.class).encode(niciraNshSpi, context));
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) {
+            NiciraSetNshSi niciraNshSi = (NiciraSetNshSi) extensionTreatment;
+            root.set(NICIRA_NSH_SI, context.codec(NiciraSetNshSi.class).encode(niciraNshSi, context));
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) {
+            NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
+            root.set(NICIRA_NSH_CH, context.codec(NiciraSetNshContextHeader.class).encode(niciraNshch, context));
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) {
+            NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
+            root.set(NICIRA_NSH_CH, context.codec(NiciraSetNshContextHeader.class).encode(niciraNshch, context));
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) {
+            NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
+            root.set(NICIRA_NSH_CH, context.codec(NiciraSetNshContextHeader.class).encode(niciraNshch, context));
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) {
+            NiciraSetNshContextHeader niciraNshch = (NiciraSetNshContextHeader) extensionTreatment;
+            root.set(NICIRA_NSH_CH, context.codec(NiciraSetNshContextHeader.class).encode(niciraNshch, context));
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())
+                || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())
+                || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())
+                || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
+            MoveExtensionTreatment mov = (MoveExtensionTreatment) extensionTreatment;
+            root.set(NICIRA_MOVE, context.codec(MoveExtensionTreatment.class).encode(mov, context));
+        }
+
+        return root;
+    }
+
+    @Override
+    public ExtensionTreatment decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse extension type
+        int typeInt = nullIsIllegal(json.get(TYPE), TYPE + MISSING_MEMBER_MESSAGE).asInt();
+        ExtensionTreatmentType type = new ExtensionTreatmentType(typeInt);
+
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type())) {
+            return context.codec(NiciraSetTunnelDst.class).decode(json, context);
+        }
+
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) {
+            return context.codec(NiciraResubmit.class).decode(json, context);
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) {
+            return context.codec(NiciraResubmitTable.class).decode(json, context);
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) {
+            return context.codec(NiciraSetNshSpi.class).decode(json, context);
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) {
+            return context.codec(NiciraSetNshSi.class).decode(json, context);
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) {
+            return context.codec(NiciraSetNshContextHeader.class).decode(json, context);
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) {
+            return context.codec(NiciraSetNshContextHeader.class).decode(json, context);
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) {
+            return context.codec(NiciraSetNshContextHeader.class).decode(json, context);
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) {
+            return context.codec(NiciraSetNshContextHeader.class).decode(json, context);
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())
+                || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())
+                || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())
+                || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
+            return context.codec(MoveExtensionTreatment.class).decode(json, context);
+        }
+        throw new UnsupportedOperationException(
+                "Driver does not support extension type " + type.toString());
+    }
 }
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java
index b3d9e28..809fa7d 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java
@@ -15,15 +15,15 @@
  */
 package org.onosproject.driver.extensions;
 
-import static com.google.common.base.MoreObjects.toStringHelper;
-
-import java.util.Objects;
-
 import org.onlab.util.KryoNamespace;
 import org.onosproject.net.NshServiceIndex;
 import org.onosproject.net.flow.AbstractExtension;
 import org.onosproject.net.flow.criteria.ExtensionSelector;
 import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
 /**
  * Implementation of NSH Service Index(SI).
  */
@@ -42,6 +42,15 @@
     }
 
     /**
+     * Creates an instance with initialized Nsh Service Index.
+     *
+     * @param nshSi nsh service index
+     */
+    public NiciraMatchNshSi(NshServiceIndex nshSi) {
+        this.nshSi = nshSi;
+    }
+
+    /**
      * Gets the nsh service index to match.
      *
      * @return the si to match
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java
index 636c83b..162ff88 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java
@@ -41,6 +41,15 @@
     }
 
     /**
+     * Creates an instance with initialized Nsh Service Path ID.
+     *
+     * @param nshSpi nsh service path ID
+     */
+    public NiciraMatchNshSpi(NshServicePathId nshSpi) {
+        this.nshSpi = nshSpi;
+    }
+
+    /**
      * Gets the network service path id to match.
      *
      * @return the nshSpi to match
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java
index e6d51db..ebf2382 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java
@@ -53,7 +53,7 @@
      * @param nshCh nsh context header
      * @param type extension treatment type
      */
-    NiciraSetNshContextHeader(NshContextHeader nshCh, ExtensionTreatmentType type) {
+    public NiciraSetNshContextHeader(NshContextHeader nshCh, ExtensionTreatmentType type) {
         this.nshCh = nshCh;
         this.type = type;
     }
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java
index 3121803..ba1a55a 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java
@@ -48,7 +48,7 @@
      *
      * @param nshSi nsh service index
      */
-    NiciraSetNshSi(NshServiceIndex nshSi) {
+    public NiciraSetNshSi(NshServiceIndex nshSi) {
         this.nshSi = nshSi;
     }
 
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java
index 17ba927..4ae8e47 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java
@@ -48,7 +48,7 @@
      *
      * @param nshSpi nsh service path id
      */
-    NiciraSetNshSpi(NshServicePathId nshSpi) {
+    public NiciraSetNshSpi(NshServicePathId nshSpi) {
         this.nshSpi = nshSpi;
     }
 
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
index 974e944..40499bb 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
@@ -54,7 +54,7 @@
      *
      * @param tunnelDst tunnel destination IPv4 address
      */
-    NiciraSetTunnelDst(Ip4Address tunnelDst) {
+    public NiciraSetTunnelDst(Ip4Address tunnelDst) {
         checkNotNull(tunnelDst);
         this.tunnelDst = tunnelDst;
     }
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/MoveExtensionTreatmentCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/MoveExtensionTreatmentCodec.java
new file mode 100644
index 0000000..4610c1b
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/MoveExtensionTreatmentCodec.java
@@ -0,0 +1,84 @@
+/*
+ * 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.DefaultMoveExtensionTreatment;
+import org.onosproject.driver.extensions.MoveExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for MoveExtensionTreatment class.
+ */
+public final class MoveExtensionTreatmentCodec extends JsonCodec<MoveExtensionTreatment> {
+
+    private static final String SRC_OFS = "srcOfs";
+    private static final String DST_OFS = "dstOfs";
+    private static final String N_BITS = "nBits";
+    private static final String SRC = "src";
+    private static final String DST = "dst";
+    private static final String TYPE = "type";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in MoveExtensionTreatment";
+
+    @Override
+    public ObjectNode encode(MoveExtensionTreatment moveExtensionTreatment, CodecContext context) {
+        checkNotNull(moveExtensionTreatment, "Move Extension Treatment cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(SRC_OFS, moveExtensionTreatment.srcOffset())
+                .put(DST_OFS, moveExtensionTreatment.dstOffset())
+                .put(N_BITS, moveExtensionTreatment.nBits())
+                .put(SRC, moveExtensionTreatment.src())
+                .put(DST, moveExtensionTreatment.dst());
+        return root;
+    }
+
+    @Override
+    public MoveExtensionTreatment decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse extension treatment type
+        ExtensionTreatmentType type = new ExtensionTreatmentType(nullIsIllegal(json.get(TYPE),
+                TYPE + MISSING_MEMBER_MESSAGE).asInt());
+
+        // parse src off set
+        int srcOfs = nullIsIllegal(json.get(SRC_OFS), SRC_OFS + MISSING_MEMBER_MESSAGE).asInt();
+
+        // parse dst off set
+        int dstOfs = nullIsIllegal(json.get(DST_OFS), DST_OFS + MISSING_MEMBER_MESSAGE).asInt();
+
+        // parse n bits
+        int nBits = nullIsIllegal(json.get(N_BITS), N_BITS + MISSING_MEMBER_MESSAGE).asInt();
+
+        // parse src
+        int src = nullIsIllegal(json.get(SRC), SRC + MISSING_MEMBER_MESSAGE).asInt();
+
+        // parse dst
+        int dst = nullIsIllegal(json.get(DST), DST + MISSING_MEMBER_MESSAGE).asInt();
+
+        MoveExtensionTreatment moveExtensionTreatment =
+                new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, src, dst, type);
+
+        return moveExtensionTreatment;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraMatchNshSiCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraMatchNshSiCodec.java
new file mode 100644
index 0000000..e6ca4a9
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraMatchNshSiCodec.java
@@ -0,0 +1,59 @@
+/*
+ * 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.NiciraMatchNshSi;
+import org.onosproject.net.NshServiceIndex;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for NiciraMatchNshSi class.
+ */
+public final class NiciraMatchNshSiCodec extends JsonCodec<NiciraMatchNshSi> {
+
+    private static final String NSH_SERVICE_INDEX = "nsi";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraMatchNshSi";
+
+    @Override
+    public ObjectNode encode(NiciraMatchNshSi niciraMatchNshSi, CodecContext context) {
+        checkNotNull(niciraMatchNshSi, "Nicira Match Nsh Si cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(NSH_SERVICE_INDEX, niciraMatchNshSi.nshSi().serviceIndex());
+        return root;
+    }
+
+    @Override
+    public NiciraMatchNshSi decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse nsh service index
+        short nshSiShort = (short) nullIsIllegal(json.get(NSH_SERVICE_INDEX),
+                NSH_SERVICE_INDEX + MISSING_MEMBER_MESSAGE).asInt();
+        NshServiceIndex nshSi = NshServiceIndex.of(nshSiShort);
+
+        NiciraMatchNshSi niciraMatchNshSi = new NiciraMatchNshSi(nshSi);
+
+        return niciraMatchNshSi;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraMatchNshSpiCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraMatchNshSpiCodec.java
new file mode 100644
index 0000000..150125a
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraMatchNshSpiCodec.java
@@ -0,0 +1,59 @@
+/*
+ * 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.NiciraMatchNshSpi;
+import org.onosproject.net.NshServicePathId;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for NiciraMatchNshSpi class.
+ */
+public final class NiciraMatchNshSpiCodec extends JsonCodec<NiciraMatchNshSpi> {
+
+    private static final String NSH_PATH_ID = "nsp";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraMatchNshSpi";
+
+    @Override
+    public ObjectNode encode(NiciraMatchNshSpi niciraMatchNshSpi, CodecContext context) {
+        checkNotNull(niciraMatchNshSpi, "Nicira Match Nsh Spi cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(NSH_PATH_ID, niciraMatchNshSpi.nshSpi().servicePathId());
+        return root;
+    }
+
+    @Override
+    public NiciraMatchNshSpi decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse nsh path id
+        int nshSpiInt = nullIsIllegal(json.get(NSH_PATH_ID),
+                NSH_PATH_ID + MISSING_MEMBER_MESSAGE).asInt();
+        NshServicePathId nshSpi = NshServicePathId.of(nshSpiInt);
+
+        NiciraMatchNshSpi niciraMatchNshSpi = new NiciraMatchNshSpi(nshSpi);
+
+        return niciraMatchNshSpi;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraResubmitCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraResubmitCodec.java
new file mode 100644
index 0000000..62db7f8
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraResubmitCodec.java
@@ -0,0 +1,60 @@
+/*
+ * 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.NiciraResubmit;
+import org.onosproject.net.PortNumber;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for NiciraResubmit class.
+ */
+public final class NiciraResubmitCodec extends JsonCodec<NiciraResubmit> {
+
+    private static final String RESUBMIT_PORT = "inPort";
+    private static final String RESUBMIT_TABLE = "table";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraResubmit";
+
+    @Override
+    public ObjectNode encode(NiciraResubmit niciraResubmit, CodecContext context) {
+        checkNotNull(niciraResubmit, "Nicira Resubmit cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(RESUBMIT_PORT, niciraResubmit.inPort().toLong())
+                .put(RESUBMIT_TABLE, niciraResubmit.table());
+        return root;
+    }
+
+    @Override
+    public NiciraResubmit decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse in port number
+        long portNumberLong = nullIsIllegal(json.get(RESUBMIT_PORT), RESUBMIT_PORT + MISSING_MEMBER_MESSAGE).asLong();
+        PortNumber portNumber = PortNumber.portNumber(portNumberLong);
+
+        NiciraResubmit niciraResubmit = new NiciraResubmit(portNumber);
+
+        return niciraResubmit;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraResubmitTableCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraResubmitTableCodec.java
new file mode 100644
index 0000000..5a8eb73
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraResubmitTableCodec.java
@@ -0,0 +1,65 @@
+/*
+ * 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.NiciraResubmitTable;
+import org.onosproject.net.PortNumber;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for NiciraResubmitTable class.
+ */
+public final class NiciraResubmitTableCodec extends JsonCodec<NiciraResubmitTable> {
+
+    private static final String RESUBMIT_PORT = "inPort";
+    private static final String RESUBMIT_TABLE = "table";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraResubmitTable";
+
+    @Override
+    public ObjectNode encode(NiciraResubmitTable niciraResubmitTable, CodecContext context) {
+        checkNotNull(niciraResubmitTable, "Nicira Resubmit Table cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(RESUBMIT_PORT, niciraResubmitTable.inPort().toLong())
+                .put(RESUBMIT_TABLE, niciraResubmitTable.table());
+        return root;
+    }
+
+    @Override
+    public NiciraResubmitTable decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse in port number
+        long portNumberLong = nullIsIllegal(json.get(RESUBMIT_PORT),
+                RESUBMIT_PORT + MISSING_MEMBER_MESSAGE).asLong();
+        PortNumber portNumber = PortNumber.portNumber(portNumberLong);
+
+        // parse table id
+        short tableId = (short) nullIsIllegal(json.get(RESUBMIT_TABLE),
+                RESUBMIT_TABLE + MISSING_MEMBER_MESSAGE).asInt();
+
+        NiciraResubmitTable niciraResubmitTable = new NiciraResubmitTable(portNumber, tableId);
+
+        return niciraResubmitTable;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshContextHeaderCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshContextHeaderCodec.java
new file mode 100644
index 0000000..9cf8bc8
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshContextHeaderCodec.java
@@ -0,0 +1,70 @@
+/*
+ * 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.NiciraSetNshContextHeader;
+import org.onosproject.net.NshContextHeader;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for NiciraSetNshContextHeader class.
+ */
+public class NiciraSetNshContextHeaderCodec extends JsonCodec<NiciraSetNshContextHeader> {
+
+    private static final String NSH_CONTEXT_HEADER = "nshch";
+    private static final String TYPE = "type";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraSetNshContextHeader";
+
+    @Override
+    public ObjectNode encode(NiciraSetNshContextHeader niciraSetNshContextHeader, CodecContext context) {
+        checkNotNull(niciraSetNshContextHeader, "Nicira Set Nsh Context Header cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(NSH_CONTEXT_HEADER, niciraSetNshContextHeader.nshCh().nshContextHeader())
+                .put(TYPE, niciraSetNshContextHeader.type().type());
+        return root;
+    }
+
+    @Override
+    public NiciraSetNshContextHeader decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse nsh context header
+        int contextHeaderInt = nullIsIllegal(json.get(NSH_CONTEXT_HEADER),
+                NSH_CONTEXT_HEADER + MISSING_MEMBER_MESSAGE).asInt();
+
+        NshContextHeader contextHeader = NshContextHeader.of(contextHeaderInt);
+
+        // parse type
+        int extensionTypeInt = nullIsIllegal(json.get(TYPE),
+                TYPE + MISSING_MEMBER_MESSAGE).asInt();
+
+        ExtensionTreatmentType type = new ExtensionTreatmentType(extensionTypeInt);
+
+        NiciraSetNshContextHeader niciraSetNshContextHeader =
+                new NiciraSetNshContextHeader(contextHeader, type);
+
+        return niciraSetNshContextHeader;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshSiCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshSiCodec.java
new file mode 100644
index 0000000..d62eb69
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshSiCodec.java
@@ -0,0 +1,60 @@
+/*
+ * 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.NiciraSetNshSi;
+import org.onosproject.net.NshServiceIndex;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for NiciraSetNshSi class.
+ */
+public final class NiciraSetNshSiCodec extends JsonCodec<NiciraSetNshSi> {
+
+    private static final String NSH_SERVICE_INDEX = "setNsi";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraSetNshSi";
+
+    @Override
+    public ObjectNode encode(NiciraSetNshSi niciraSetNshSi, CodecContext context) {
+        checkNotNull(niciraSetNshSi, "Nicira Set Nsh Si cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(NSH_SERVICE_INDEX, niciraSetNshSi.nshSi().serviceIndex());
+        return root;
+    }
+
+    @Override
+    public NiciraSetNshSi decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse service index port
+        short serviceIndexShort = (short) nullIsIllegal(json.get(NSH_SERVICE_INDEX),
+                NSH_SERVICE_INDEX + MISSING_MEMBER_MESSAGE).asInt();
+
+        NshServiceIndex index = NshServiceIndex.of(serviceIndexShort);
+
+        NiciraSetNshSi niciraSetNshSi = new NiciraSetNshSi(index);
+
+        return niciraSetNshSi;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshSpiCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshSpiCodec.java
new file mode 100644
index 0000000..e6c209d
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetNshSpiCodec.java
@@ -0,0 +1,60 @@
+/*
+ * 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.NiciraSetNshSpi;
+import org.onosproject.net.NshServicePathId;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for NiciraSetNshSpi class.
+ */
+public final class NiciraSetNshSpiCodec extends JsonCodec<NiciraSetNshSpi> {
+
+    private static final String NSH_PATH_ID = "setNsp";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraSetNshSpi";
+
+    @Override
+    public ObjectNode encode(NiciraSetNshSpi niciraSetNshSpi, CodecContext context) {
+        checkNotNull(niciraSetNshSpi, "Nicira Set Nsh Spi cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(NSH_PATH_ID, niciraSetNshSpi.nshSpi().servicePathId());
+        return root;
+    }
+
+    @Override
+    public NiciraSetNshSpi decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse service path id
+        int servicePathIdInt = nullIsIllegal(json.get(NSH_PATH_ID),
+                NSH_PATH_ID + MISSING_MEMBER_MESSAGE).asInt();
+
+        NshServicePathId pathId = NshServicePathId.of(servicePathIdInt);
+
+        NiciraSetNshSpi niciraSetNshSpi = new NiciraSetNshSpi(pathId);
+
+        return niciraSetNshSpi;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetTunnelDstCodec.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetTunnelDstCodec.java
new file mode 100644
index 0000000..fc7fa1b
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/NiciraSetTunnelDstCodec.java
@@ -0,0 +1,59 @@
+/*
+ * 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.onlab.packet.Ip4Address;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.driver.extensions.NiciraSetTunnelDst;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+/**
+ * JSON Codec for NiciraSetTunnelDst class.
+ */
+public final class NiciraSetTunnelDstCodec extends JsonCodec<NiciraSetTunnelDst> {
+
+    private static final String TUNNEL_DST = "tunnelDst";
+
+    private static final String MISSING_MEMBER_MESSAGE = " member is required in NiciraSetTunnelDst";
+
+    @Override
+    public ObjectNode encode(NiciraSetTunnelDst niciraSetTunnelDst, CodecContext context) {
+        checkNotNull(niciraSetTunnelDst, "Nicira Set Tunnel DST cannot be null");
+        ObjectNode root = context.mapper().createObjectNode()
+                .put(TUNNEL_DST, niciraSetTunnelDst.tunnelDst().toString());
+        return root;
+    }
+
+    @Override
+    public NiciraSetTunnelDst decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+
+        // parse tunnel destination IP address
+        String dstIp = nullIsIllegal(json.get(TUNNEL_DST), TUNNEL_DST + MISSING_MEMBER_MESSAGE).asText();
+
+        Ip4Address tunnelDst = Ip4Address.valueOf(dstIp);
+
+        NiciraSetTunnelDst niciraSetTunnelDst = new NiciraSetTunnelDst(tunnelDst);
+
+        return niciraSetTunnelDst;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/package-info.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/package-info.java
new file mode 100644
index 0000000..45dc2f5
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/codec/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+/**
+ * Implementations of the codec broker and NICIRA and OFDPA extension JSON codecs.
+ */
+package org.onosproject.driver.extensions.codec;
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionSelectorInterpreter.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionSelectorInterpreter.java
index 740f40f..37726ba 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionSelectorInterpreter.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionSelectorInterpreter.java
@@ -17,7 +17,7 @@
 package org.onosproject.openflow.controller;
 
 import com.google.common.annotations.Beta;
-import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.codec.ExtensionSelectorCodec;
 import org.onosproject.net.flow.criteria.ExtensionSelector;
 import org.onosproject.net.flow.criteria.ExtensionSelectorType;
 import org.projectfloodlight.openflow.protocol.OFFactory;
@@ -27,7 +27,7 @@
  * Interprets extension selectors and converts them to/from OpenFlow objects.
  */
 @Beta
-public interface ExtensionSelectorInterpreter extends HandlerBehaviour {
+public interface ExtensionSelectorInterpreter extends ExtensionSelectorCodec {
 
     /**
      * Returns true if the given extension selector is supported by this
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java
index 8a6eeda..f511ef3 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionTreatmentInterpreter.java
@@ -17,7 +17,7 @@
 package org.onosproject.openflow.controller;
 
 import com.google.common.annotations.Beta;
-import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.codec.ExtensionTreatmentCodec;
 import org.onosproject.net.flow.instructions.ExtensionTreatment;
 import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
 import org.projectfloodlight.openflow.protocol.OFFactory;
@@ -27,7 +27,7 @@
  * Interprets extension treatments and converts them to/from OpenFlow objects.
  */
 @Beta
-public interface ExtensionTreatmentInterpreter extends HandlerBehaviour {
+public interface ExtensionTreatmentInterpreter extends ExtensionTreatmentCodec {
 
     /**
      * Returns true if the given extension treatment is supported by this
@@ -55,5 +55,4 @@
      * @throws UnsupportedOperationException if driver does not support extension type
      */
     ExtensionTreatment mapAction(OFAction action) throws UnsupportedOperationException;
-
 }