[ONOS-6208]Implemention of onos and loxi for OVS NAT and connection tracking support

Change-Id: I782422d41fdacc805b523b57c3bd0b6e67e483a2
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
index f65c168..e9715a6 100644
--- 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
@@ -39,6 +39,10 @@
         NICIRA_MATCH_NSH_CH3(4),
         NICIRA_MATCH_NSH_CH4(5),
         NICIRA_MATCH_ENCAP_ETH_TYPE(6),
+        NICIRA_MATCH_CONNTRACK_STATE(7),
+        NICIRA_MATCH_CONNTRACK_ZONE(8),
+        NICIRA_MATCH_CONNTRACK_MARK(9),
+        NICIRA_MATCH_CONNTRACK_LABEL(10),
         OFDPA_MATCH_VLAN_VID(16),
         OFDPA_MATCH_OVID(17),
         OFDPA_MATCH_MPLS_L2_PORT(18),
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 1371e42..d11a9a9 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
@@ -48,6 +48,9 @@
         NICIRA_RESUBMIT_TABLE(14),
         NICIRA_PUSH_NSH(38),
         NICIRA_POP_NSH(39),
+        NICIRA_CT(40),
+        NICIRA_NAT(41),
+        NICIRA_CT_CLEAR(42),
         OFDPA_SET_VLAN_ID(64),
         OFDPA_SET_MPLS_TYPE(65),
         OFDPA_SET_OVID(66),
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCt.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCt.java
new file mode 100644
index 0000000..62e7506
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCt.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2017-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 com.google.common.collect.Maps;
+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.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Nicira ct extension instruction.
+ */
+public class NiciraCt extends AbstractExtension implements ExtensionTreatment {
+
+    private int flags;
+    private long zoneSrc;
+    private int zone;
+    private short recircTable;
+    private int alg;
+    private List<ExtensionTreatment> nestedActions;
+    private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+    /**
+     * Creates a new nicicra ct instruction.
+     */
+    public NiciraCt() {
+        flags = 0;
+        zoneSrc = 0L;
+        zone = 0;
+        alg = 0;
+        recircTable = 0xFF;
+        nestedActions = new ArrayList<>();
+    }
+
+    /**
+     * Creates a new nicicra ct instruction.
+     * @param flags  zero or commit(0x01)
+     * @param zoneSrc If 'zone_src' is nonzero, this specifies that the zone should be
+     *                sourced from a field zone_src[ofs:ofs+nbits].
+     * @param zone this is the union of zone_imm and zone_ofs_nbits
+     *             If 'zone_src' is zero, then the value of 'zone_imm'
+     *             will be used as the connection tracking zone
+     * @param recircTable  Recirculate to a specific table or 0xff for no recirculation
+     * @param alg  Well-known port number for the protocol, 0 indicates no ALG is required
+     * @param actions a sequence of zero or more OpenFlow actions
+     */
+    public NiciraCt(int flags, long zoneSrc, int zone, short recircTable, int alg, List<ExtensionTreatment> actions) {
+        this.flags = flags;
+        this.zoneSrc = zoneSrc;
+        this.zone = zone;
+        this.recircTable = recircTable;
+        this.alg = alg;
+        this.nestedActions = actions;
+    }
+
+    @Override
+    public ExtensionTreatmentType type() {
+        return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type();
+    }
+
+    /**
+     * Get Nicira Conntrack flags.
+     * @return flags
+     */
+    public int niciraCtFlags() {
+        return flags;
+    }
+
+    /**
+     * Get Nicira Conntrack zone.
+     * @return zone
+     */
+    public int niciraCtZone() {
+        return zone;
+    }
+
+    /**
+     * Get Nicira Conntrack zone src.
+     * @return zoneSrc
+     */
+    public long niciraCtZoneSrc() {
+        return zoneSrc;
+    }
+
+    /**
+     * Get Nicira Conntrack alg.
+     * @return alg
+     */
+    public int niciraCtAlg() {
+        return alg;
+    }
+
+    /**
+     * Get Nicira Conntrack Recirc table.
+     * @return recirc table
+     */
+    public short niciraCtRecircTable() {
+        return recircTable;
+    }
+
+    /**
+     * Get Nicira Conntrack Recirc table.
+     * @return list extension treatment
+     */
+    public List<ExtensionTreatment> niciraCtNestActions() {
+        return nestedActions;
+    }
+
+    @Override
+    public void deserialize(byte[] data) {
+        Map<String, Object> values = appKryo.deserialize(data);
+        flags = (int) values.get("flags");
+        zoneSrc = (long) values.get("zoneSrc");
+        zone = (int) values.get("zone");
+        recircTable = (short) values.get("recircTable");
+        alg = (int) values.get("alg");
+        nestedActions = (List) values.get("nestedActions");
+    }
+
+    @Override
+    public byte[] serialize() {
+        Map<String, Object> values = Maps.newHashMap();
+        values.put("flags", flags);
+        values.put("zoneSrc", zoneSrc);
+        values.put("zone", zone);
+        values.put("recircTable", recircTable);
+        values.put("alg", alg);
+        values.put("nestedActions", nestedActions);
+        return appKryo.serialize(values);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type(), flags, zone, zoneSrc, alg, recircTable, nestedActions);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NiciraCt) {
+            NiciraCt that = (NiciraCt) obj;
+            return Objects.equals(flags, that.flags) &&
+                    Objects.equals(zone, that.zone) &&
+                    Objects.equals(zoneSrc, that.zoneSrc) &&
+                    Objects.equals(alg, that.alg) &&
+                    Objects.equals(recircTable, that.recircTable) &&
+                    Objects.equals(nestedActions, that.nestedActions) &&
+                    Objects.equals(this.type(), that.type());
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("flags", flags)
+                .add("zoneSrc", zoneSrc)
+                .add("zone", zone)
+                .add("recircTable", recircTable)
+                .add("alg", alg)
+                .add("nestedActions", nestedActions)
+                .toString();
+    }
+}
\ No newline at end of file
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCtClear.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCtClear.java
new file mode 100644
index 0000000..d7aada7
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCtClear.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017-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 org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+/**
+ * Nicira conntrack clear extension instruction.
+ */
+public class NiciraCtClear extends AbstractExtension implements ExtensionTreatment {
+
+    private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+    /**
+     * Creates a conntrack clear instruction.
+     */
+    public NiciraCtClear() {
+    }
+
+    @Override
+    public ExtensionTreatmentType type() {
+        return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type();
+    }
+
+    @Override
+    public void deserialize(byte[] data) {
+    }
+
+    @Override
+    public byte[] serialize() {
+        return appKryo.serialize(0);
+    }
+
+    @Override
+    public int hashCode() {
+        return 1;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NiciraCtClear) {
+            return true;
+        }
+        return false;
+    }
+}
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 4bd1aa5..b9367fc 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
@@ -28,6 +28,9 @@
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.match.MatchField;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmConntrackMark;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmConntrackStateMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmConntrackZone;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmEncapEthType;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmNsi;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmNsp;
@@ -66,6 +69,22 @@
                                          .type())) {
             return true;
         }
+        if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE
+                .type())) {
+            return true;
+        }
+        if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE
+                .type())) {
+            return true;
+        }
+        if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK
+                .type())) {
+            return true;
+        }
+        if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_LABEL
+                .type())) {
+            return true;
+        }
         return false;
     }
 
@@ -97,6 +116,20 @@
         if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) {
             // TODO
         }
+
+        if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type())) {
+            NiciraMatchCtState niciraMatchCtState = (NiciraMatchCtState) extensionSelector;
+            return factory.oxms().conntrackStateMasked(U32.of(niciraMatchCtState.ctState()),
+                    U32.of(niciraMatchCtState.ctStateMask()));
+        }
+        if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE.type())) {
+            NiciraMatchCtZone niciraMatchCtZone = (NiciraMatchCtZone) extensionSelector;
+            return factory.oxms().conntrackZone(U16.of(niciraMatchCtZone.ctZone()));
+        }
+        if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK.type())) {
+            NiciraMatchCtMark niciraMatchCtMark = (NiciraMatchCtMark) extensionSelector;
+            return factory.oxms().conntrackMark(U32.of(niciraMatchCtMark.ctMark()));
+        }
         return null;
     }
 
@@ -115,7 +148,18 @@
             OFOxmEncapEthType oxmField = (OFOxmEncapEthType) oxm;
             return new NiciraMatchEncapEthType(oxmField.getValue().getRaw());
         }
-
+        if (oxm.getMatchField() == MatchField.CONNTRACK_STATE) {
+            OFOxmConntrackStateMasked oxmField = (OFOxmConntrackStateMasked) oxm;
+            return new NiciraMatchCtState(oxmField.getValue().getRaw(), oxmField.getMask().getRaw());
+        }
+        if (oxm.getMatchField() == MatchField.CONNTRACK_ZONE) {
+            OFOxmConntrackZone oxmField = (OFOxmConntrackZone) oxm;
+            return new NiciraMatchCtZone(oxmField.getValue().getRaw());
+        }
+        if (oxm.getMatchField() == MatchField.CONNTRACK_MARK) {
+            OFOxmConntrackMark oxmField = (OFOxmConntrackMark) oxm;
+            return new NiciraMatchCtMark(oxmField.getValue().getRaw());
+        }
         return null;
     }
 
@@ -136,6 +180,15 @@
                 || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) {
             return new NiciraMatchNshContextHeader(type);
         }
+        if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type())) {
+            return new NiciraMatchCtState();
+        }
+        if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE.type())) {
+            return new NiciraMatchCtZone();
+        }
+        if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK.type())) {
+            return new NiciraMatchCtMark();
+        }
         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 3a0778e..bcc8872 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
@@ -18,8 +18,10 @@
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onlab.util.Tools.nullIsIllegal;
-
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Bytes;
 import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
 import org.onosproject.codec.CodecContext;
 import org.onosproject.net.NshContextHeader;
 import org.onosproject.net.NshServiceIndex;
@@ -35,7 +37,9 @@
 import org.projectfloodlight.openflow.protocol.action.OFAction;
 import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
 import org.projectfloodlight.openflow.protocol.action.OFActionNicira;
+import org.projectfloodlight.openflow.protocol.action.OFActionNiciraCt;
 import org.projectfloodlight.openflow.protocol.action.OFActionNiciraMove;
+import org.projectfloodlight.openflow.protocol.action.OFActionNiciraNat;
 import org.projectfloodlight.openflow.protocol.action.OFActionNiciraResubmit;
 import org.projectfloodlight.openflow.protocol.action.OFActionNiciraResubmitTable;
 import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
@@ -54,6 +58,7 @@
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunGpeNp;
 import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst;
 import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IPv6Address;
 import org.projectfloodlight.openflow.types.MacAddress;
 import org.projectfloodlight.openflow.types.U16;
 import org.projectfloodlight.openflow.types.U32;
@@ -61,6 +66,9 @@
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Interpreter for Nicira OpenFlow treatment extensions.
  */
@@ -80,9 +88,19 @@
     private static final int TUN_IPV4_DST = 0x00014004;
     private static final int TUN_ID = 0x12008;
 
+    private static final int NAT_RANGE_IPV4_MIN = 0x01;
+    private static final int NAT_RANGE_IPV4_MAX = 0x02;
+    private static final int NAT_RANGE_IPV6_MIN = 0x04;
+    private static final int NAT_RANGE_IPV6_MAX = 0x08;
+    private static final int NAT_RANGE_PROTO_MIN = 0x10;
+    private static final int NAT_RANGE_PROTO_MAX = 0x20;
+
     private static final int SUB_TYPE_RESUBMIT = 1;
     private static final int SUB_TYPE_RESUBMIT_TABLE = 14;
     private static final int SUB_TYPE_MOVE = 6;
+    private static final int SUB_TYPE_CT = 35;
+    private static final int SUB_TYPE_NAT = 36;
+    private static final int SUB_TYPE_CT_CLEAR = 43;
     private static final int SUB_TYPE_PUSH_NSH = 38;
     private static final int SUB_TYPE_POP_NSH = 39;
 
@@ -199,6 +217,15 @@
                                           .type())) {
             return true;
         }
+        if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type())) {
+            return true;
+        }
+        if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type())) {
+            return true;
+        }
+        if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type())) {
+            return true;
+        }
         return false;
     }
 
@@ -299,6 +326,70 @@
             action.setDst(mov.dst());
             return action.build();
         }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type())) {
+            NiciraCt niciraCt = (NiciraCt) extensionTreatment;
+            OFActionNiciraCt.Builder ctAction = factory.actions().buildNiciraCt();
+            ctAction.setFlags(niciraCt.niciraCtFlags());
+            ctAction.setZoneSrc(niciraCt.niciraCtZoneSrc());
+            ctAction.setZone(niciraCt.niciraCtZone());
+            ctAction.setRecircTable(niciraCt.niciraCtRecircTable());
+            ctAction.setAlg(niciraCt.niciraCtAlg());
+
+            for (ExtensionTreatment nestedTreatment : niciraCt.niciraCtNestActions()) {
+                if (nestedTreatment instanceof NiciraNat) {
+                    NiciraNat niciraNat = (NiciraNat) nestedTreatment;
+                    OFActionNiciraNat.Builder action = factory.actions().buildNiciraNat();
+                    action.setFlags(niciraNat.niciraNatFlags());
+
+                    int presetFlags = niciraNat.niciraNatPresentFlags();
+                    action.setRangePresent(presetFlags);
+
+                    List<IPv4Address> ipv4RangeList = Lists.newArrayList();
+                    List<IPv6Address> ipv6RangeList = Lists.newArrayList();
+                    List<U16> portRangeList = Lists.newArrayList();
+                    List<U8> padList = Lists.newArrayList();
+                    if ((presetFlags & NAT_RANGE_IPV4_MIN) != 0) {
+                        ipv4RangeList.add(IPv4Address.of(niciraNat.niciraNatIpAddressMin().getIp4Address().toString()));
+                    }
+                    if ((presetFlags & NAT_RANGE_IPV4_MAX) != 0) {
+                        ipv4RangeList.add(IPv4Address.of(niciraNat.niciraNatIpAddressMax().getIp4Address().toString()));
+                    }
+
+                    if ((presetFlags & NAT_RANGE_IPV6_MIN) != 0) {
+                        ipv6RangeList.add(IPv6Address.of(niciraNat.niciraNatIpAddressMin().getIp6Address().toString()));
+                    }
+                    if ((presetFlags & NAT_RANGE_IPV6_MAX) != 0) {
+                        ipv6RangeList.add(IPv6Address.of(niciraNat.niciraNatIpAddressMax().getIp6Address().toString()));
+                    }
+
+                    if ((presetFlags & NAT_RANGE_PROTO_MIN) != 0) {
+                        portRangeList.add(U16.of(niciraNat.niciraNatPortMin()));
+                    }
+                    if ((presetFlags & NAT_RANGE_PROTO_MAX) != 0) {
+                        portRangeList.add(U16.of(niciraNat.niciraNatPortMax()));
+                    }
+
+                    for (; (ipv6RangeList.size() * 16 + ipv4RangeList.size() * 4
+                            + portRangeList.size() * 2 + padList.size()) % 8 != 0;) {
+                        padList.add(U8.ofRaw((byte) 0));
+                    }
+
+                    action.setIpv4Range(ipv4RangeList);
+                    action.setIpv6Range(ipv6RangeList);
+                    action.setPortRange(portRangeList);
+                    action.setPad(padList);
+
+                    //nat action must be nested in ct action
+                    List<OFAction> actions = Lists.newArrayList();
+                    actions.add(action.build());
+                    ctAction.setActions(actions);
+                }
+            }
+            return ctAction.build();
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type())) {
+            return factory.actions().niciraCtClear();
+        }
         return null;
     }
 
@@ -404,14 +495,87 @@
                     case SUB_TYPE_RESUBMIT:
                         OFActionNiciraResubmit resubmitAction = (OFActionNiciraResubmit) nicira;
                         return new NiciraResubmit(PortNumber.portNumber(resubmitAction.getInPort()));
-                case SUB_TYPE_PUSH_NSH:
-                    return new NiciraPushNsh();
-                case SUB_TYPE_POP_NSH:
-                    return new NiciraPopNsh();
-                case SUB_TYPE_RESUBMIT_TABLE:
-                    OFActionNiciraResubmitTable resubmitTable = (OFActionNiciraResubmitTable) nicira;
-                    return new NiciraResubmitTable(PortNumber.portNumber(resubmitTable.getInPort()),
-                                                   resubmitTable.getTable());
+                    case SUB_TYPE_PUSH_NSH:
+                        return new NiciraPushNsh();
+                    case SUB_TYPE_POP_NSH:
+                        return new NiciraPopNsh();
+                    case SUB_TYPE_RESUBMIT_TABLE:
+                        OFActionNiciraResubmitTable resubmitTable = (OFActionNiciraResubmitTable) nicira;
+                        return new NiciraResubmitTable(PortNumber.portNumber(resubmitTable.getInPort()),
+                                                       resubmitTable.getTable());
+                    case SUB_TYPE_CT:
+                        OFActionNiciraCt ctAction = (OFActionNiciraCt) nicira;
+                        List<OFAction> actions = ctAction.getActions();
+                        for (OFAction act : actions) {
+                            OFActionExperimenter ctExperimenter = (OFActionExperimenter) act;
+                            if (Long.valueOf(ctExperimenter.getExperimenter()).intValue() == TYPE_NICIRA) {
+                                OFActionNicira actionNicira = (OFActionNicira) ctExperimenter;
+                                switch (actionNicira.getSubtype()) {
+                                    case SUB_TYPE_NAT:
+                                        OFActionNiciraNat natAction = (OFActionNiciraNat) actionNicira;
+                                        int portMin = 0;
+                                        int portMax = 0;
+                                        IpAddress ipAddressMin = IpAddress.valueOf(0);
+                                        IpAddress ipAddressMax = IpAddress.valueOf(0);
+                                        //FIXME: we need to get ipv6 and port from list<ipv4> temporarily,
+                                        // becase loxi don't know how to arrange these data to corresonding field.
+                                        IPv4Address[] arrays = (IPv4Address[]) natAction
+                                                .getIpv4Range().toArray(new IPv4Address[0]);
+                                        int index = 0;
+                                        if ((natAction.getRangePresent() & NAT_RANGE_IPV4_MIN) != 0) {
+                                            ipAddressMin = IpAddress.valueOf(arrays[index++].toString());
+                                        }
+                                        if ((natAction.getRangePresent() & NAT_RANGE_IPV4_MAX) != 0) {
+                                            ipAddressMax = IpAddress.valueOf(arrays[index++].toString());
+                                        }
+                                        if ((natAction.getRangePresent() & NAT_RANGE_IPV6_MIN) != 0) {
+                                            byte[]  bytes = Bytes.concat(arrays[index++].getBytes(),
+                                                    arrays[index++].getBytes(),
+                                                    arrays[index++].getBytes(),
+                                                    arrays[index++].getBytes());
+
+                                            ipAddressMin = IpAddress.valueOf(IpAddress.Version.INET6, bytes);
+                                        }
+                                        if ((natAction.getRangePresent() & NAT_RANGE_IPV6_MAX) != 0) {
+                                            byte[]  bytes = Bytes.concat(arrays[index++].getBytes(),
+                                                    arrays[index++].getBytes(),
+                                                    arrays[index++].getBytes(),
+                                                    arrays[index++].getBytes());
+
+                                            ipAddressMax = IpAddress.valueOf(IpAddress.Version.INET6, bytes);
+                                        }
+                                        if ((natAction.getRangePresent() & NAT_RANGE_PROTO_MIN) != 0) {
+                                            portMin = arrays[index].getInt() >> 16 & 0x0000ffff;
+                                        }
+                                        if ((natAction.getRangePresent() & NAT_RANGE_PROTO_MAX) != 0) {
+                                            portMax = arrays[index].getInt() & 0x0000ffff;
+                                        }
+                                        List<ExtensionTreatment> treatments = new ArrayList<>();
+                                        NiciraNat natTreatment = new NiciraNat(natAction.getFlags(),
+                                                natAction.getRangePresent(),
+                                                portMin, portMax,
+                                                ipAddressMin, ipAddressMax);
+                                        treatments.add(natTreatment);
+                                        return new NiciraCt(ctAction.getFlags(),
+                                                ctAction.getZoneSrc(),
+                                                ctAction.getZone(),
+                                                ctAction.getRecircTable(),
+                                                ctAction.getAlg(),
+                                                treatments);
+                                    default:
+                                        throw new UnsupportedOperationException("Driver does not support nested" +
+                                                " in ct action extension subtype " + actionNicira.getSubtype());
+                                }
+                            }
+                        }
+                        return new NiciraCt(ctAction.getFlags(),
+                                ctAction.getZoneSrc(),
+                                ctAction.getZone(),
+                                ctAction.getRecircTable(),
+                                ctAction.getAlg(),
+                                new ArrayList<>());
+                    case SUB_TYPE_CT_CLEAR:
+                        return new NiciraCtClear();
                     default:
                         throw new UnsupportedOperationException("Driver does not support extension subtype "
                                 + nicira.getSubtype());
@@ -502,6 +666,15 @@
         if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C2_TO_TUN_ID.type())) {
             return NiciraMoveTreatmentFactory.createNiciraMovNshC2ToTunId();
         }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type())) {
+            return new NiciraCt();
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type())) {
+            return new NiciraNat();
+        }
+        if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type())) {
+            return new NiciraCtClear();
+        }
         throw new UnsupportedOperationException("Driver does not support extension type " + type.toString());
     }
 
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtMark.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtMark.java
new file mode 100644
index 0000000..562025a
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtMark.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2017-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 java.util.Map;
+import java.util.Objects;
+
+import com.google.common.collect.Maps;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira conntrack mark extension selector.
+ */
+public class NiciraMatchCtMark extends AbstractExtension implements ExtensionSelector {
+
+    private long ctMark;
+    private long ctMarkMask;
+
+    private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+    /**
+     * Creates a new conntrack mark selector.
+     */
+    NiciraMatchCtMark() {
+        ctMark = 0L;
+        ctMarkMask = ~0L;
+    }
+
+    /**
+     * Creates a new conntrack state selector with given mark.
+     *
+     * @param ctMark conntrack mark
+     */
+    public NiciraMatchCtMark(long ctMark) {
+        this.ctMark = ctMark;
+        this.ctMarkMask = ~0L;
+    }
+
+    /**
+     * Creates a new conntrack state selector with given mark.
+     *
+     * @param ctMark conntrack mark
+     * @param mask   conntrack mark mask
+     */
+    public NiciraMatchCtMark(long ctMark, long mask) {
+        this.ctMark = ctMark;
+        this.ctMarkMask = mask;
+    }
+
+    /**
+     * Gets the conntrack mark.
+     *
+     * @return ctMark
+     */
+    public long ctMark() {
+        return ctMark;
+    }
+
+    /**
+     * Gets the conntrack mark mask.
+     *
+     * @return ctMarkMask
+     */
+    public long ctMarkMask() {
+        return ctMarkMask;
+    }
+
+    @Override
+    public ExtensionSelectorType type() {
+        return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK.type();
+    }
+
+    @Override
+    public void deserialize(byte[] data) {
+        Map<String, Object> values = appKryo.deserialize(data);
+        ctMark = (long) values.get("ctMark");
+        ctMarkMask = (long) values.get("ctMarkMask");
+    }
+
+    @Override
+    public byte[] serialize() {
+        Map<String, Object> values = Maps.newHashMap();
+        values.put("ctMark", ctMark);
+        values.put("ctMarkMask", ctMarkMask);
+        return appKryo.serialize(values);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ctMark, ctMarkMask);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NiciraMatchCtMark) {
+            NiciraMatchCtMark that = (NiciraMatchCtMark) obj;
+            return Objects.equals(ctMark, that.ctMark)
+                    && Objects.equals(ctMarkMask, that.ctMarkMask);
+
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("ctMark", ctMark)
+                .add("ctMarkMask", ctMarkMask)
+                .toString();
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtState.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtState.java
new file mode 100644
index 0000000..098e264
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtState.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2017-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 java.util.Map;
+import java.util.Objects;
+
+import com.google.common.collect.Maps;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+
+import com.google.common.base.MoreObjects;
+/**
+ * Nicira conntrack state extension selector.
+ */
+public class NiciraMatchCtState extends AbstractExtension implements ExtensionSelector {
+
+    private long ctState;
+    private long ctStateMask;
+
+    private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+    /**
+     * Creates a new conntrack state selector.
+     */
+    NiciraMatchCtState() {
+        ctState = 0L;
+        ctStateMask = ~0L;
+    }
+
+    /**
+     * Creates a new conntrack state selector with given state.
+     *
+     * @param ctState conntrack state
+     * @param mask conntrack state mask
+     */
+    public NiciraMatchCtState(long ctState, long mask) {
+        this.ctState = ctState;
+        this.ctStateMask = mask;
+    }
+
+    /**
+     * Gets the conntrack state.
+     *
+     * @return ctState
+     */
+    public long ctState() {
+        return ctState;
+    }
+
+    /**
+     * Gets the conntrack state mask.
+     *
+     * @return ctStateMask
+     */
+    public long ctStateMask() {
+        return ctStateMask;
+    }
+
+    @Override
+    public ExtensionSelectorType type() {
+        return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type();
+    }
+
+    @Override
+    public void deserialize(byte[] data) {
+        Map<String, Object> values = appKryo.deserialize(data);
+        ctState = (long) values.get("ctState");
+        ctStateMask = (long) values.get("ctStateMask");
+    }
+
+    @Override
+    public byte[] serialize() {
+        Map<String, Object> values = Maps.newHashMap();
+        values.put("ctState", ctState);
+        values.put("ctStateMask", ctStateMask);
+        return appKryo.serialize(values);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ctState, ctStateMask);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NiciraMatchCtState) {
+            NiciraMatchCtState that = (NiciraMatchCtState) obj;
+            return Objects.equals(ctState, that.ctState)
+                    && Objects.equals(ctStateMask, that.ctStateMask);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("ctState", ctState)
+                .add("mask", ctStateMask)
+                .toString();
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtZone.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtZone.java
new file mode 100644
index 0000000..5752ee8
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtZone.java
@@ -0,0 +1,99 @@
+/*
+ * 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 java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Nicira conntrack zone extension selector.
+ */
+public class NiciraMatchCtZone extends AbstractExtension implements ExtensionSelector {
+
+    private int ctZone;
+
+    private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+    /**
+     * Creates a new conntrack zone selector.
+     */
+    NiciraMatchCtZone() {
+        ctZone = 0;
+    }
+
+    /**
+     * Creates a new conntrack zone selector with given zone.
+     *
+     * @param ctZone conntrack zone
+     */
+    public NiciraMatchCtZone(int ctZone) {
+        this.ctZone = ctZone;
+    }
+
+    /**
+     * Gets the conntrack zone.
+     *
+     * @return ctZone
+     */
+    public int ctZone() {
+        return ctZone;
+    }
+
+    @Override
+    public ExtensionSelectorType type() {
+        return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE.type();
+    }
+
+    @Override
+    public void deserialize(byte[] data) {
+        ctZone = (int) (appKryo.deserialize(data));
+    }
+
+    @Override
+    public byte[] serialize() {
+        return appKryo.serialize(ctZone);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ctZone);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NiciraMatchCtZone) {
+            NiciraMatchCtZone that = (NiciraMatchCtZone) obj;
+            return Objects.equals(ctZone, that.ctZone());
+
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass()).add("ctZone", ctZone).toString();
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNat.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNat.java
new file mode 100644
index 0000000..9259d82
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNat.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2017-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 com.google.common.collect.Maps;
+import org.onlab.packet.IpAddress;
+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 org.onosproject.store.serializers.IpAddressSerializer;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Nicira nat extension instruction.
+ */
+public class NiciraNat extends AbstractExtension implements ExtensionTreatment {
+    private int flags;
+    private int presentFlags;
+    private int portMin;
+    private int portMax;
+    private IpAddress ipAddressMin;
+    private IpAddress ipAddressMax;
+    private final KryoNamespace appKryo = new KryoNamespace.Builder()
+            .register(new IpAddressSerializer(), IpAddress.class)
+            .register(byte[].class)
+            .build();
+
+    /**
+     * Creates a new nat instruction.
+     */
+    public NiciraNat() {
+        flags = 0;
+        presentFlags = 0;
+        portMin = 0;
+        portMax = 0;
+        ipAddressMin = IpAddress.valueOf(0);
+        ipAddressMax = IpAddress.valueOf(0);
+    }
+
+    /**
+     * Creates a new nat instruction.
+     * @param flags  nat flags
+     * @param presentFlags  nat present flags
+     * @param portMin  min port
+     * @param portMax  max port
+     * @param ipAddressMin  min ip address
+     * @param ipAddressMax  max ip address
+     */
+    public NiciraNat(int flags, int presentFlags, int portMin, int portMax, IpAddress ipAddressMin,
+                     IpAddress ipAddressMax) {
+        this.flags = flags;
+        this.presentFlags = presentFlags;
+        this.portMin = portMin;
+        this.portMax = portMax;
+        this.ipAddressMin = ipAddressMin;
+        this.ipAddressMax = ipAddressMax;
+    }
+
+    @Override
+    public ExtensionTreatmentType type() {
+        return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type();
+    }
+
+    /**
+     * Get Nicira nat flags.
+     * @return flags
+     */
+    public int niciraNatFlags() {
+        return flags;
+    }
+
+    /**
+     * Get Nicira present flags.
+     * @return present flags
+     */
+    public int niciraNatPresentFlags() {
+        return presentFlags;
+    }
+
+    /**
+     * Get Nicira Nat min port.
+     * @return min port
+     */
+    public int niciraNatPortMin() {
+        return portMin;
+    }
+
+    /**
+     * Get Nicira Nat max port.
+     * @return max port
+     */
+    public int niciraNatPortMax() {
+        return portMax;
+    }
+
+    /**
+     * Get Nicira Nat min ip address.
+     * @return min ipaddress
+     */
+    public IpAddress niciraNatIpAddressMin() {
+        return ipAddressMin;
+    }
+
+    /**
+     * Get Nicira Nat max ip address.
+     * @return max ipaddress
+     */
+    public IpAddress niciraNatIpAddressMax() {
+        return ipAddressMax;
+    }
+
+    @Override
+    public void deserialize(byte[] data) {
+        Map<String, Object> values = appKryo.deserialize(data);
+        flags = (int) values.get("flags");
+        presentFlags = (int) values.get("presentFlags");
+        portMin = (int) values.get("portMin");
+        portMax = (int) values.get("portMax");
+        ipAddressMin = (IpAddress) values.get("ipAddressMin");
+        ipAddressMax = (IpAddress) values.get("ipAddressMax");
+    }
+
+    @Override
+    public byte[] serialize() {
+        Map<String, Object> values = Maps.newHashMap();
+        values.put("flags", flags);
+        values.put("presentFlags", presentFlags);
+        values.put("portMin", portMin);
+        values.put("portMax", portMax);
+        values.put("ipAddressMin", ipAddressMin);
+        values.put("ipAddressMax", ipAddressMax);
+        return appKryo.serialize(values);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type(), flags, presentFlags, portMin, portMax, ipAddressMin, ipAddressMax);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof NiciraNat) {
+            NiciraNat that = (NiciraNat) obj;
+            return Objects.equals(flags, that.flags) &&
+                    Objects.equals(presentFlags, that.presentFlags) &&
+                    Objects.equals(portMin, that.portMin) &&
+                    Objects.equals(portMax, that.portMax) &&
+                    Objects.equals(ipAddressMin, that.ipAddressMin) &&
+                    Objects.equals(ipAddressMax, that.ipAddressMax) &&
+                    Objects.equals(this.type(), that.type());
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("flags", flags)
+                .add("present_flags", presentFlags)
+                .add("portMin", portMin)
+                .add("portMax", portMax)
+                .add("ipAddressMin", ipAddressMin)
+                .add("ipAddressMax", ipAddressMax)
+                .toString();
+    }
+}
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 0666cc5..5c245a8 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
@@ -979,7 +979,7 @@
                         match.get(MatchField.EXP_ODU_SIG_ID).getTslen(),
                         match.get(MatchField.EXP_ODU_SIG_ID).getTsmap());
                 builder.add(matchOduSignalId(oduSignalId));
-            break;
+                break;
             case EXP_ODU_SIGTYPE:
                 try {
                     U8 oduSigType = match.get(MatchField.EXP_ODU_SIGTYPE);
@@ -1043,6 +1043,39 @@
                     }
                 }
                 break;
+            case CONNTRACK_STATE:
+                if (selectorInterpreter != null &&
+                        selectorInterpreter.supported(ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type())) {
+                    try {
+                        OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.CONNTRACK_STATE);
+                        builder.extension(selectorInterpreter.mapOxm(oxm), deviceId);
+                    } catch (UnsupportedOperationException e) {
+                        log.debug(e.getMessage());
+                    }
+                }
+                break;
+            case CONNTRACK_ZONE:
+                if (selectorInterpreter != null &&
+                        selectorInterpreter.supported(ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE.type())) {
+                    try {
+                        OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.CONNTRACK_ZONE);
+                        builder.extension(selectorInterpreter.mapOxm(oxm), deviceId);
+                    } catch (UnsupportedOperationException e) {
+                        log.debug(e.getMessage());
+                    }
+                }
+                break;
+            case CONNTRACK_MARK:
+                if (selectorInterpreter != null &&
+                        selectorInterpreter.supported(ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK.type())) {
+                    try {
+                        OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.CONNTRACK_MARK);
+                        builder.extension(selectorInterpreter.mapOxm(oxm), deviceId);
+                    } catch (UnsupportedOperationException e) {
+                        log.debug(e.getMessage());
+                    }
+                }
+                break;
             case OFDPA_OVID:
                 if (selectorInterpreter != null &&
                         selectorInterpreter.supported(ExtensionSelectorTypes.OFDPA_MATCH_OVID.type())) {