Merge into master from pull request #48:
Fixes for java OXM stuff and implementation for Match structures in versions 1.2,1.3 (https://github.com/floodlight/loxigen/pull/48)
diff --git a/java_gen/import_cleaner.py b/java_gen/import_cleaner.py
index 83897d4..d84d76b 100755
--- a/java_gen/import_cleaner.py
+++ b/java_gen/import_cleaner.py
@@ -1,4 +1,34 @@
-#!/usr/bin/python
+# Copyright 2013, Big Switch Networks, Inc.
+#
+# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
+# the following special exception:
+#
+# LOXI Exception
+#
+# As a special exception to the terms of the EPL, you may distribute libraries
+# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
+# that copyright and licensing notices generated by LoxiGen are not altered or removed
+# from the LoxiGen Libraries and the notice provided below is (i) included in
+# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
+# documentation for the LoxiGen Libraries, if distributed in binary form.
+#
+# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
+#
+# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
+# a copy of the EPL at:
+#
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# 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
+# EPL for the specific language governing permissions and limitations
+# under the EPL.
+
+# A utility for naively cleaning of redundant 'import' statements in java source file.
+# This utility searches the name of the imported class in the code and if not found,
+# removes the corresponding import statement.
+# This utility assumes class/package naming that follows java naming conventions.
 
 import sys
 import re
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 944b536..d1adce0 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -55,7 +55,64 @@
     virtual_interfaces = set(['OFOxm', 'OFInstruction', 'OFFlowMod', 'OFBsnVport' ])
 
     OxmMapEntry = namedtuple("OxmMapEntry", ["type_name", "value", "masked" ])
-    oxm_map = { "OFOxmInPortMasked": OxmMapEntry("OFPort", "IN_PORT", True) }
+    oxm_map = { "OFOxmInPort":              OxmMapEntry("OFPort", "IN_PORT", False),
+                "OFOxmInPortMasked":        OxmMapEntry("OFPort", "IN_PORT", True),
+                "OFOxmInPhyPort":           OxmMapEntry("OFPort", "IN_PHY_PORT", False),
+                "OFOxmInPhyPortMasked":     OxmMapEntry("OFPort", "IN_PHY_PORT", True),
+                "OFOxmMetadata":            OxmMapEntry("OFMetadata", "METADATA", False),
+                "OFOxmMetadataMasked":      OxmMapEntry("OFMetadata", "METADATA", True),
+                "OFOxmEthDst":              OxmMapEntry("MacAddress", "ETH_DST", False),
+                "OFOxmEthDstMasked":        OxmMapEntry("MacAddress", "ETH_DST", True),
+                "OFOxmEthSrc":              OxmMapEntry("MacAddress", "ETH_SRC", False),
+                "OFOxmEthSrcMasked":        OxmMapEntry("MacAddress", "ETH_SRC", True),
+                "OFOxmEthType":             OxmMapEntry("EthType", "ETH_TYPE", False),
+                "OFOxmEthTypeMasked":       OxmMapEntry("EthType", "ETH_TYPE", True),
+                "OFOxmVlanVid":             OxmMapEntry("VlanVid", "VLAN_VID", False),
+                "OFOxmVlanVidMasked":       OxmMapEntry("VlanVid", "VLAN_VID", True),
+                "OFOxmVlanPcp":             OxmMapEntry("VlanPcp", "VLAN_PCP", False),
+                "OFOxmVlanPcpMasked":       OxmMapEntry("VlanPcp", "VLAN_PCP", True),
+                "OFOxmIpDscp":              OxmMapEntry("IpDscp", "IP_DSCP", False),
+                "OFOxmIpDscpMasked":        OxmMapEntry("IpDscp", "IP_DSCP", True),
+                "OFOxmIpEcn":               OxmMapEntry("IpEcn", "IP_ECN", False),
+                "OFOxmIpEcnMasked":         OxmMapEntry("IpEcn", "IP_ECN", True),
+                "OFOxmIpProto":             OxmMapEntry("IpProtocol", "IP_PROTO", False),
+                "OFOxmIpProtoMasked":       OxmMapEntry("IpProtocol", "IP_PROTO", True),
+                "OFOxmIpv4Src":             OxmMapEntry("IPv4", "IPV4_SRC", False),
+                "OFOxmIpv4SrcMasked":       OxmMapEntry("IPv4", "IPV4_SRC", True),
+                "OFOxmIpv4Dst":             OxmMapEntry("IPv4", "IPV4_DST", False),
+                "OFOxmIpv4DstMasked":       OxmMapEntry("IPv4", "IPV4_DST", True),
+                "OFOxmTcpSrc":              OxmMapEntry("TransportPort", "TCP_SRC", False),
+                "OFOxmTcpSrcMasked":        OxmMapEntry("TransportPort", "TCP_SRC", True),
+                "OFOxmTcpDst":              OxmMapEntry("TransportPort", "TCP_DST", False),
+                "OFOxmTcpDstMasked":        OxmMapEntry("TransportPort", "TCP_DST", True),
+                "OFOxmUdpSrc":              OxmMapEntry("TransportPort", "UDP_SRC", False),
+                "OFOxmUdpSrcMasked":        OxmMapEntry("TransportPort", "UDP_SRC", True),
+                "OFOxmUdpDst":              OxmMapEntry("TransportPort", "UDP_DST", False),
+                "OFOxmUdpDstMasked":        OxmMapEntry("TransportPort", "UDP_DST", True),
+                "OFOxmSctpSrc":             OxmMapEntry("TransportPort", "SCTP_SRC", False),
+                "OFOxmSctpSrcMasked":       OxmMapEntry("TransportPort", "SCTP_SRC", True),
+                "OFOxmSctpDst":             OxmMapEntry("TransportPort", "SCTP_DST", False),
+                "OFOxmSctpDstMasked":       OxmMapEntry("TransportPort", "SCTP_DST", True),
+                "OFOxmIcmpv4Type":          OxmMapEntry("ICMPv4Type", "ICMPV4_TYPE", False),
+                "OFOxmIcmpv4TypeMasked":    OxmMapEntry("ICMPv4Type", "ICMPV4_TYPE", True),
+                "OFOxmIcmpv4Code":          OxmMapEntry("ICMPv4Code", "ICMPV4_CODE", False),
+                "OFOxmIcmpv4CodeMasked":    OxmMapEntry("ICMPv4Code", "ICMPV4_CODE", True),
+                "OFOxmArpOp":               OxmMapEntry("ArpOpcode", "ARP_OP", False),
+                "OFOxmArpOpMasked":         OxmMapEntry("ArpOpcode", "ARP_OP", True),
+                "OFOxmArpSpa":              OxmMapEntry("IPv4", "ARP_SPA", False),
+                "OFOxmArpSpaMasked":        OxmMapEntry("IPv4", "ARP_SPA", True),
+                "OFOxmArpTpa":              OxmMapEntry("IPv4", "ARP_TPA", False),
+                "OFOxmArpTpaMasked":        OxmMapEntry("IPv4", "ARP_TPA", True),
+                "OFOxmArpSha":              OxmMapEntry("MacAddress", "ARP_SHA", False),
+                "OFOxmArpShaMasked":        OxmMapEntry("MacAddress", "ARP_SHA", True),
+                "OFOxmArpTha":              OxmMapEntry("MacAddress", "ARP_THA", False),
+                "OFOxmArpThaMasked":        OxmMapEntry("MacAddress", "ARP_THA", True),
+                "OFOxmIpv6Src":             OxmMapEntry("IPv6", "IPV6_SRC", False),
+                "OFOxmIpv6SrcMasked":       OxmMapEntry("IPv6", "IPV6_SRC", True),
+                "OFOxmIpv6Dst":             OxmMapEntry("IPv6", "IPV6_DST", False),
+                "OFOxmIpv6DstMasked":       OxmMapEntry("IPv6", "IPV6_DST", True),
+                "OFOxmIpv6Flabel":          OxmMapEntry("IPv6FlowLabel", "IPV6_FLABEL", False),
+                "OFOxmIpv6FlabelMasked":    OxmMapEntry("IPv6FlowLabel", "IPV6_FLABEL", True) }
 
     @property
     @memoize
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
index eb02bc3..cbd3b14 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchField.java
@@ -34,7 +34,7 @@
             new MatchField<OFPort>("in_port", MatchFields.IN_PORT);
     
     public final static MatchField<OFPort> IN_PHY_PORT =
-            new MatchField<OFPort>("in_phy_port", MatchFields.PHYSICAL_PORT,
+            new MatchField<OFPort>("in_phy_port", MatchFields.IN_PHY_PORT,
                     new Prerequisite<OFPort>(MatchField.IN_PORT));
     
     public final static MatchField<OFMetadata> METADATA =
@@ -137,7 +137,7 @@
                     new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6));
 
     public final static MatchField<IPv6FlowLabel> IPV6_FLABEL =
-            new MatchField<IPv6FlowLabel>("ipv6_flabel", MatchFields.IPV6_FLOWLABEL,
+            new MatchField<IPv6FlowLabel>("ipv6_flabel", MatchFields.IPV6_FLABEL,
                     new Prerequisite<EthType>(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6));
 
     public String getName() {
diff --git a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java
index 309f91f..ed79237 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/MatchFields.java
@@ -3,7 +3,7 @@
 // MUST BE ORDERED BY THE ORDER OF OF SPEC!!!
 public enum MatchFields {
     IN_PORT,
-    PHYSICAL_PORT,
+    IN_PHY_PORT,
     METADATA,
     ETH_DST,
     ETH_SRC,
@@ -30,5 +30,5 @@
     ARP_THA,
     IPV6_SRC,
     IPV6_DST,
-    IPV6_FLOWLABEL,
+    IPV6_FLABEL,
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/OFMetadata.java b/java_gen/pre-written/src/main/java/org/openflow/types/OFMetadata.java
index e82bc40..86799eb 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/OFMetadata.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/OFMetadata.java
@@ -41,4 +41,26 @@
         return OFMetadata.of(this.u64.applyMask(mask.u64));
     }
 
+    @Override
+    public boolean equals(Object arg0) {
+        if (!(arg0 instanceof OFMetadata))
+            return false;
+        OFMetadata other = (OFMetadata)arg0;
+
+        return this.u64.equals(other.u64);
+    }
+
+    @Override
+    public int hashCode() {
+        int prime = 53;
+        return this.u64.hashCode() * prime;
+    }
+
+    @Override
+    public String toString() {
+        return "Metadata: " + u64.toString();
+    }
+
+
+
 }
diff --git a/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java b/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
index 2c5687e..1ebb807 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/types/TransportPort.java
@@ -5,24 +5,24 @@
 
 /**
  * Represents L4 (Transport Layer) port (TCP, UDP, etc.)
- * 
+ *
  * @author Yotam Harchol (yotam.harchol@bigswitch.com)
  */
 public class TransportPort implements OFValueType<TransportPort> {
-    
+
     static final int LENGTH = 2;
     static final int MAX_PORT = 0xFFFF;
     static final int MIN_PORT = 0;
-    
-    public static final TransportPort NO_MASK = TransportPort.of(0xFFFFFFFF);
+
+    public static final TransportPort NO_MASK = new TransportPort(0xFFFFFFFF);
     public static final TransportPort FULL_MASK = TransportPort.of(0x0);
 
     private final int port;
-    
+
     private TransportPort(int port) {
         this.port = port;
     }
-    
+
     public static TransportPort of(int port) {
         if (port < MIN_PORT || port > MAX_PORT) {
             throw new IllegalArgumentException("Illegal transport layer port number: " + port);
@@ -34,7 +34,7 @@
     public int getLength() {
         return LENGTH;
     }
-    
+
     public int getPort() {
         return port;
     }
@@ -74,5 +74,5 @@
     public TransportPort applyMask(TransportPort mask) {
         return TransportPort.of(this.port & mask.port);
     }
-    
+
 }
diff --git a/java_gen/templates/custom/OFMatchV3Ver12.Builder.java b/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
index ba739bc..b5fa630 100644
--- a/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
+++ b/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
@@ -1,73 +1,108 @@
 
-    @Override
-    public <F extends OFValueType<F>> F get(MatchField<F> field)
-            throws UnsupportedOperationException {
-        // FIXME yotam - please replace with real implementation
-        return null;
+    private OFOxmList.Builder oxmListBuilder;
+
+    private synchronized void initBuilder() {
+        if (oxmListBuilder != null)
+            return;
+        oxmListBuilder = new OFOxmList.Builder();
+    }
+
+    private synchronized void updateOxmList() {
+        this.oxmList = this.oxmListBuilder.build();
+        this.oxmListSet = true;
+    }
+
+    private <F extends OFValueType<F>> OFOxm<F> getOxm(MatchField<F> field) {
+//:: if has_parent:
+        return this.oxmListSet ? this.oxmList.get(field) : parentMessage.oxmList.get(field);
+//:: else:
+        return this.oxmListSet ? this.oxmList.get(field) : null;
+//:: #endif
     }
 
     @Override
-    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+    public synchronized <F extends OFValueType<F>> F get(MatchField<F> field)
             throws UnsupportedOperationException {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        OFOxm<F> value = getOxm(field);
+        if (value == null)
+            return null;
+        return value.getValue();
+    }
+
+    @Override
+    public synchronized <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        OFOxm<F> value = getOxm(field);
+        if (value == null || !value.isMasked())
+            return null;
+        // TODO: If changing OXMs to extend Masked, then use it here
+        return Masked.of(value.getValue(), value.getMask());
     }
 
     @Override
     public boolean supports(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        return supportsField(field);
     }
 
     @Override
     public boolean supportsMasked(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        return supportsField(field);
     }
 
     @Override
-    public boolean isExact(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+    public synchronized boolean isExact(MatchField<?> field) {
+        OFOxm<?> value = getOxm(field);
+        return (value != null && !value.isMasked());
     }
 
     @Override
-    public boolean isFullyWildcarded(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+    public synchronized boolean isFullyWildcarded(MatchField<?> field) {
+        OFOxm<?> value = getOxm(field);
+        return (value == null);
     }
 
     @Override
-    public boolean isPartiallyMasked(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+    public synchronized boolean isPartiallyMasked(MatchField<?> field) {
+        OFOxm<?> value = getOxm(field);
+        return (value != null && value.isMasked());
     }
 
     @Override
-    public <F extends OFValueType<F>> Match.Builder setExact(
+    public synchronized <F extends OFValueType<F>> Match.Builder setExact(
             MatchField<F> field, F value) {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValue(value, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
     }
 
     @Override
-    public <F extends OFValueType<F>> Match.Builder setMasked(
+    public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
             MatchField<F> field, F value, F mask) {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValueAndMask(value, mask, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
     }
 
     @Override
-    public <F extends OFValueType<F>> Match.Builder setMasked(
+    public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
             MatchField<F> field, Masked<F> valueWithMask) {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromMasked(valueWithMask, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
     }
 
     @Override
-    public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
-        // FIXME yotam - please replace with real implementation
-        return null;
+    public synchronized <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+        initBuilder();
+        this.oxmListBuilder.unset(field);
+        updateOxmList();
+        return this;
     }
 
     @Override
@@ -77,5 +112,6 @@
 
     @Override
     public void writeTo(ChannelBuffer bb) {
-        // FIXME yotam - please replace with real implementation        
-    }
+        // TODO: What should this write?
+        throw new UnsupportedOperationException("Builder cannot be written");
+    }
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFMatchV3Ver12.java b/java_gen/templates/custom/OFMatchV3Ver12.java
index ec7bfcc..a4cc51c 100644
--- a/java_gen/templates/custom/OFMatchV3Ver12.java
+++ b/java_gen/templates/custom/OFMatchV3Ver12.java
@@ -2,43 +2,108 @@
     @Override
     public <F extends OFValueType<F>> F get(MatchField<F> field)
             throws UnsupportedOperationException {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        if (!supports(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+        OFOxm<F> oxm = this.oxmList.get(field);
+
+        if (oxm == null || !field.arePrerequisitesOK(this))
+            return null;
+
+        return oxm.getValue();
     }
 
     @Override
     public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
             throws UnsupportedOperationException {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        if (!supportsMasked(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support masked matching on field " + field.getName());
+
+        OFOxm<F> oxm = this.oxmList.get(field);
+
+        if (oxm == null || !field.arePrerequisitesOK(this))
+            return null;
+
+        if (oxm.getMask() == null)
+            return null;
+
+        // TODO: Make OfOxm extend Masked and just return the OXM?
+        return Masked.of(oxm.getValue(), oxm.getMask());
+    }
+
+    private static boolean supportsField(MatchField<?> field) {
+        switch (field.id) {
+            case IN_PORT:
+            case IN_PHY_PORT:
+            case METADATA:
+            case ETH_DST:
+            case ETH_SRC:
+            case ETH_TYPE:
+            case VLAN_VID:
+            case VLAN_PCP:
+            case IP_DSCP:
+            case IP_ECN:
+            case IP_PROTO:
+            case IPV4_SRC:
+            case IPV4_DST:
+            case TCP_SRC:
+            case TCP_DST:
+            case UDP_SRC:
+            case UDP_DST:
+            case SCTP_SRC:
+            case SCTP_DST:
+            case ICMPV4_TYPE:
+            case ICMPV4_CODE:
+            case ARP_OP:
+            case ARP_SPA:
+            case ARP_TPA:
+            case ARP_SHA:
+            case ARP_THA:
+            case IPV6_SRC:
+            case IPV6_DST:
+            case IPV6_FLABEL:
+                return true;
+            default:
+                return false;
+        }
     }
 
     @Override
     public boolean supports(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        return supportsField(field);
     }
 
     @Override
     public boolean supportsMasked(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        return supportsField(field);
     }
 
     @Override
     public boolean isExact(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        if (!supports(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+        OFOxm<?> oxm = this.oxmList.get(field);
+
+        return oxm != null && !oxm.isMasked();
     }
 
     @Override
     public boolean isFullyWildcarded(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        if (!supports(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+        OFOxm<?> oxm = this.oxmList.get(field);
+
+        return oxm == null;
     }
 
     @Override
     public boolean isPartiallyMasked(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
-    }
+        if (!supports(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+        OFOxm<?> oxm = this.oxmList.get(field);
+
+        return oxm != null && oxm.isMasked();
+    }
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
index 81e8d4e..b5fa630 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
@@ -1,73 +1,108 @@
 
-    @Override
-    public <F extends OFValueType<F>> F get(MatchField<F> field)
-            throws UnsupportedOperationException {
-        // FIXME yotam - please replace with real implementation
-        return null;
+    private OFOxmList.Builder oxmListBuilder;
+
+    private synchronized void initBuilder() {
+        if (oxmListBuilder != null)
+            return;
+        oxmListBuilder = new OFOxmList.Builder();
+    }
+
+    private synchronized void updateOxmList() {
+        this.oxmList = this.oxmListBuilder.build();
+        this.oxmListSet = true;
+    }
+
+    private <F extends OFValueType<F>> OFOxm<F> getOxm(MatchField<F> field) {
+//:: if has_parent:
+        return this.oxmListSet ? this.oxmList.get(field) : parentMessage.oxmList.get(field);
+//:: else:
+        return this.oxmListSet ? this.oxmList.get(field) : null;
+//:: #endif
     }
 
     @Override
-    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+    public synchronized <F extends OFValueType<F>> F get(MatchField<F> field)
             throws UnsupportedOperationException {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        OFOxm<F> value = getOxm(field);
+        if (value == null)
+            return null;
+        return value.getValue();
+    }
+
+    @Override
+    public synchronized <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        OFOxm<F> value = getOxm(field);
+        if (value == null || !value.isMasked())
+            return null;
+        // TODO: If changing OXMs to extend Masked, then use it here
+        return Masked.of(value.getValue(), value.getMask());
     }
 
     @Override
     public boolean supports(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        return supportsField(field);
     }
 
     @Override
     public boolean supportsMasked(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        return supportsField(field);
     }
 
     @Override
-    public boolean isExact(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+    public synchronized boolean isExact(MatchField<?> field) {
+        OFOxm<?> value = getOxm(field);
+        return (value != null && !value.isMasked());
     }
 
     @Override
-    public boolean isFullyWildcarded(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+    public synchronized boolean isFullyWildcarded(MatchField<?> field) {
+        OFOxm<?> value = getOxm(field);
+        return (value == null);
     }
 
     @Override
-    public boolean isPartiallyMasked(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+    public synchronized boolean isPartiallyMasked(MatchField<?> field) {
+        OFOxm<?> value = getOxm(field);
+        return (value != null && value.isMasked());
     }
 
     @Override
-    public <F extends OFValueType<F>> Match.Builder setExact(
+    public synchronized <F extends OFValueType<F>> Match.Builder setExact(
             MatchField<F> field, F value) {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValue(value, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
     }
 
     @Override
-    public <F extends OFValueType<F>> Match.Builder setMasked(
+    public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
             MatchField<F> field, F value, F mask) {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValueAndMask(value, mask, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
     }
 
     @Override
-    public <F extends OFValueType<F>> Match.Builder setMasked(
+    public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
             MatchField<F> field, Masked<F> valueWithMask) {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromMasked(valueWithMask, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
     }
 
     @Override
-    public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
-        // FIXME yotam - please replace with real implementation
-        return null;
+    public synchronized <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+        initBuilder();
+        this.oxmListBuilder.unset(field);
+        updateOxmList();
+        return this;
     }
 
     @Override
@@ -77,6 +112,6 @@
 
     @Override
     public void writeTo(ChannelBuffer bb) {
-        // FIXME yotam - please replace with real implementation        
-    }
-
+        // TODO: What should this write?
+        throw new UnsupportedOperationException("Builder cannot be written");
+    }
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.java b/java_gen/templates/custom/OFMatchV3Ver13.java
index ec7bfcc..a4cc51c 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.java
@@ -2,43 +2,108 @@
     @Override
     public <F extends OFValueType<F>> F get(MatchField<F> field)
             throws UnsupportedOperationException {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        if (!supports(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+        OFOxm<F> oxm = this.oxmList.get(field);
+
+        if (oxm == null || !field.arePrerequisitesOK(this))
+            return null;
+
+        return oxm.getValue();
     }
 
     @Override
     public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
             throws UnsupportedOperationException {
-        // FIXME yotam - please replace with real implementation
-        return null;
+        if (!supportsMasked(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support masked matching on field " + field.getName());
+
+        OFOxm<F> oxm = this.oxmList.get(field);
+
+        if (oxm == null || !field.arePrerequisitesOK(this))
+            return null;
+
+        if (oxm.getMask() == null)
+            return null;
+
+        // TODO: Make OfOxm extend Masked and just return the OXM?
+        return Masked.of(oxm.getValue(), oxm.getMask());
+    }
+
+    private static boolean supportsField(MatchField<?> field) {
+        switch (field.id) {
+            case IN_PORT:
+            case IN_PHY_PORT:
+            case METADATA:
+            case ETH_DST:
+            case ETH_SRC:
+            case ETH_TYPE:
+            case VLAN_VID:
+            case VLAN_PCP:
+            case IP_DSCP:
+            case IP_ECN:
+            case IP_PROTO:
+            case IPV4_SRC:
+            case IPV4_DST:
+            case TCP_SRC:
+            case TCP_DST:
+            case UDP_SRC:
+            case UDP_DST:
+            case SCTP_SRC:
+            case SCTP_DST:
+            case ICMPV4_TYPE:
+            case ICMPV4_CODE:
+            case ARP_OP:
+            case ARP_SPA:
+            case ARP_TPA:
+            case ARP_SHA:
+            case ARP_THA:
+            case IPV6_SRC:
+            case IPV6_DST:
+            case IPV6_FLABEL:
+                return true;
+            default:
+                return false;
+        }
     }
 
     @Override
     public boolean supports(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        return supportsField(field);
     }
 
     @Override
     public boolean supportsMasked(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        return supportsField(field);
     }
 
     @Override
     public boolean isExact(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        if (!supports(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+        OFOxm<?> oxm = this.oxmList.get(field);
+
+        return oxm != null && !oxm.isMasked();
     }
 
     @Override
     public boolean isFullyWildcarded(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
+        if (!supports(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+        OFOxm<?> oxm = this.oxmList.get(field);
+
+        return oxm == null;
     }
 
     @Override
     public boolean isPartiallyMasked(MatchField<?> field) {
-        // FIXME yotam - please replace with real implementation
-        return false;
-    }
+        if (!supports(field))
+            throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+        OFOxm<?> oxm = this.oxmList.get(field);
+
+        return oxm != null && oxm.isMasked();
+    }
\ No newline at end of file
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index bcaf961..4ea6ac9 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -106,7 +106,7 @@
                     );
         }
         //:: if os.path.exists("%s/custom/%s.Builder.java" % (template_dir, msg.name)):
-        //:: include("custom/%s.Builder.java" % msg.name, msg=msg)
+        //:: include("custom/%s.Builder.java" % msg.name, msg=msg, has_parent=True)
         //:: #endif
 
     }
@@ -129,7 +129,7 @@
                 );
         }
         //:: if os.path.exists("%s/custom/%s.Builder.java" % (template_dir, msg.name)):
-        //:: include("custom/%s.Builder.java" % msg.name, msg=msg)
+        //:: include("custom/%s.Builder.java" % msg.name, msg=msg, has_parent=False)
         //:: #endif
 
     }
diff --git a/java_gen/templates/of_factory_class.java b/java_gen/templates/of_factory_class.java
index e83344b..adf5df1 100644
--- a/java_gen/templates/of_factory_class.java
+++ b/java_gen/templates/of_factory_class.java
@@ -85,4 +85,63 @@
 //:: #endif
     }
 
+//:: if factory.interface.name == 'OFOxms':
+    @SuppressWarnings("unchecked")
+    public <F extends OFValueType<F>> OFOxm<F> fromValue(F value, MatchField<F> field) {
+        switch (field.id) {
+            //:: for oxm_name in model.oxm_map:
+            //::    type_name, value, masked = model.oxm_map[oxm_name]
+            //::    if masked:
+            //::        continue
+            //::    #endif
+            //::    method_name = oxm_name.replace('OFOxm', '')
+            //::    method_name = method_name[0].lower() + method_name[1:]
+            case ${value}:
+                //:: # The cast to Object is done to avoid some javac bug that in some versions cannot handle cast from generic type to other types but Object
+                return (OFOxm<F>)((Object)${method_name}((${type_name})((Object)value)));
+            //:: #endfor
+            default:
+                return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public <F extends OFValueType<F>> OFOxm<F> fromValueAndMask(F value, F mask, MatchField<F> field) {
+        switch (field.id) {
+            //:: for oxm_name in model.oxm_map:
+            //::    type_name, value, masked = model.oxm_map[oxm_name]
+            //::    if not masked:
+            //::        continue
+            //::    #endif
+            //::    method_name = oxm_name.replace('OFOxm', '')
+            //::    method_name = method_name[0].lower() + method_name[1:]
+            case ${value}:
+                //:: # The cast to Object is done to avoid some javac bug that in some versions cannot handle cast from generic type to other types but Object
+                return (OFOxm<F>)((Object)${method_name}((${type_name})((Object)value), (${type_name})((Object)mask)));
+            //:: #endfor
+            default:
+                return null;
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public <F extends OFValueType<F>> OFOxm<F> fromMasked(Masked<F> masked, MatchField<F> field) {
+        switch (field.id) {
+            //:: for oxm_name in model.oxm_map:
+            //::    type_name, value, masked = model.oxm_map[oxm_name]
+            //::    if not masked:
+            //::        continue
+            //::    #endif
+            //::    method_name = oxm_name.replace('OFOxm', '')
+            //::    method_name = method_name[0].lower() + method_name[1:]
+            case ${value}:
+                //:: # The cast to Object is done to avoid some javac bug that in some versions cannot handle cast from generic type to other types but Object
+                return (OFOxm<F>)((Object)${method_name}((${type_name})((Object)(masked.getValue())), (${type_name})((Object)(masked.getMask()))));
+            //:: #endfor
+            default:
+                return null;
+        }
+    }
+//:: #endif
+
 }
diff --git a/java_gen/templates/of_factory_interface.java b/java_gen/templates/of_factory_interface.java
index fcb690f..329539f 100644
--- a/java_gen/templates/of_factory_interface.java
+++ b/java_gen/templates/of_factory_interface.java
@@ -54,4 +54,10 @@
 //:: #endfor
 
     OFMessageReader<${factory.base_class}> getReader();
+
+//:: if factory.name == 'OFOxms':
+    public <F extends OFValueType<F>> OFOxm<F> fromValue(F value, MatchField<F> field);
+    public <F extends OFValueType<F>> OFOxm<F> fromValueAndMask(F value, F mask, MatchField<F> field);
+    public <F extends OFValueType<F>> OFOxm<F> fromMasked(Masked<F> masked, MatchField<F> field);
+//:: #endif
 }
diff --git a/test_data/of13/flow_add.data b/test_data/of13/flow_add.data
index 10b3d2f..666da50 100644
--- a/test_data/of13/flow_add.data
+++ b/test_data/of13/flow_add.data
@@ -1,6 +1,6 @@
 -- binary
 04 0e # version, type
-00 48 # length
+00 80 # length
 12 34 56 78 # xid
 
 fe dc ba 98 76 54 32 10 # cookie
@@ -21,8 +21,23 @@
 00 00 # pad
 
 00 01 # match.type
-00 04 # match.length
-00 00 00 00 # pad
+00 3F # match.length # 59 bytes OXMs + 4 bytes match header
+
+80 00 01 08 # match.oxm_list[0].type_len - IN_PORT
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+
+80 00 0A 02 # match.oxm_list[1].type_len - ETH_TYPE
+86 DD # match.oxm_list[1].value - ETH_TYPE = IPv6
+
+80 00 14 01 # match.oxm_list[2].type_len - IP Proto
+06 # match.oxm_list[2].value = IP_PROTO = TCP
+
+80 00 35 20 # match.oxm_list[3].type_len - IPV6_SRC
+1C CA FE 1C B1 10 1C 00 00 28 00 00 00 00 00 00 # match.oxm_list[3].value
+FF FF FF FF FF F0 FF FF 1C 2C 3C 00 00 00 00 00 # match.oxm_list[3].mask
+
+00 # match.pad
 
 00 01 # instructions[0].type
 00 08 # instructions[0].length
@@ -46,7 +61,14 @@
     out_port=6,
     out_group=8,
     flags=0,
-    match=ofp.match(oxm_list=[]),
+    match=ofp.match(oxm_list=[
+        ofp.oxm.in_port_masked(value=4, value_mask=5),
+        ofp.oxm.eth_type(value=0x86dd),
+        ofp.oxm.ip_proto(value=6),
+        ofp.oxm.ipv6_src_masked(
+            value     ='\x1C\xCA\xFE\x1C\xB1\x10\x1C\x00\x00\x28\x00\x00\x00\x00\x00\x00',
+            value_mask='\xFF\xFF\xFF\xFF\xFF\xF0\xFF\xFF\x1C\x2C\x3C\x00\x00\x00\x00\x00')
+        ]),
     instructions=[
         ofp.instruction.goto_table(table_id=4),
         ofp.instruction.goto_table(table_id=7)])
@@ -62,11 +84,19 @@
     .setOutPort(OFPort.of(6))
     .setOutGroup(8)
     .setFlags(0)
-    .setMatch(factory.buildMatchV3().build()) // FIXME: @yotam: replace once we have generic ofmatch
+    .setMatch(
+        factory.buildMatchV3()
+            .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
+            .setExact(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6)
+            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setMasked(MatchField.IPV6_SRC, 
+                       IPv6.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
+                       IPv6.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
+        	.build()
+    )
     .setInstructions(
         ImmutableList.<OFInstruction>of(
-            factory.instructions().gotoTable((short) 4),
-            factory.instructions().gotoTable((short) 7)
+        	factory.instructions().gotoTable((short)4),
+        	factory.instructions().gotoTable((short)7)
         )
     );
-
diff --git a/test_data/of13/flow_delete.data b/test_data/of13/flow_delete.data
new file mode 100644
index 0000000..22f07c2
--- /dev/null
+++ b/test_data/of13/flow_delete.data
@@ -0,0 +1,102 @@
+-- binary
+04 0e # version, type
+00 80 # length
+12 34 56 78 # xid
+
+fe dc ba 98 76 54 32 10 # cookie
+
+ff 00 ff 00 ff 00 ff 00 # cookie_mask
+
+03 # table_id
+03 # _command
+00 05 # idle_timeout
+00 0a # hard_timeout
+17 70 # priority
+
+00 00 00 32 # buffer_id
+00 00 00 06 # out_port
+
+00 00 00 08 # out_group
+00 00 # flags
+00 00 # pad
+
+00 01 # match.type
+00 3F # match.length # 59 bytes OXMs + 4 bytes match header
+
+80 00 01 08 # match.oxm_list[0].type_len - IN_PORT
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+
+80 00 0A 02 # match.oxm_list[1].type_len - ETH_TYPE
+86 DD # match.oxm_list[1].value - ETH_TYPE = IPv6
+
+80 00 14 01 # match.oxm_list[2].type_len - IP Proto
+06 # match.oxm_list[2].value = IP_PROTO = TCP
+
+80 00 35 20 # match.oxm_list[3].type_len - IPV6_SRC
+1C CA FE 1C B1 10 1C 00 00 28 00 00 00 00 00 00 # match.oxm_list[3].value
+FF FF FF FF FF F0 FF FF 1C 2C 3C 00 00 00 00 00 # match.oxm_list[3].mask
+
+00 # match.pad
+
+00 01 # instructions[0].type
+00 08 # instructions[0].length
+04 # instructions[0].table_id
+00 00 00 # pad
+
+00 01 # instructions[1].type
+00 08 # instructions[1].length
+07 # instructions[1].table_id
+00 00 00 # pad
+-- python
+ofp.message.flow_delete(
+    xid=0x12345678,
+    cookie=0xFEDCBA9876543210,
+    cookie_mask=0xFF00FF00FF00FF00,
+    table_id=3,
+    idle_timeout=5,
+    hard_timeout=10,
+    priority=6000,
+    buffer_id=50,
+    out_port=6,
+    out_group=8,
+    flags=0,
+    match=ofp.match(oxm_list=[
+        ofp.oxm.in_port_masked(value=4, value_mask=5),
+        ofp.oxm.eth_type(value=0x86dd),
+        ofp.oxm.ip_proto(value=6),
+        ofp.oxm.ipv6_src_masked(
+            value     ='\x1C\xCA\xFE\x1C\xB1\x10\x1C\x00\x00\x28\x00\x00\x00\x00\x00\x00',
+            value_mask='\xFF\xFF\xFF\xFF\xFF\xF0\xFF\xFF\x1C\x2C\x3C\x00\x00\x00\x00\x00')
+        ]),
+    instructions=[
+        ofp.instruction.goto_table(table_id=4),
+        ofp.instruction.goto_table(table_id=7)])
+-- java
+builder.setXid(0x12345678)
+    .setCookie(U64.parseHex("FEDCBA9876543210"))
+    .setCookieMask(U64.parseHex("FF00FF00FF00FF00"))
+    .setTableId((byte) 3)
+    .setIdleTimeout(5)
+    .setHardTimeout(10)
+    .setPriority(6000)
+    .setBufferId(50)
+    .setOutPort(OFPort.of(6))
+    .setOutGroup(8)
+    .setFlags(0)
+    .setMatch(
+        factory.buildMatchV3()
+            .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
+            .setExact(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6)
+            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setMasked(MatchField.IPV6_SRC, 
+                       IPv6.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
+                       IPv6.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
+        	.build()
+    )
+    .setInstructions(
+        ImmutableList.<OFInstruction>of(
+        	factory.instructions().gotoTable((short)4),
+        	factory.instructions().gotoTable((short)7)
+        )
+    );
diff --git a/test_data/of13/flow_delete_strict.data b/test_data/of13/flow_delete_strict.data
new file mode 100644
index 0000000..ab21088
--- /dev/null
+++ b/test_data/of13/flow_delete_strict.data
@@ -0,0 +1,102 @@
+-- binary
+04 0e # version, type
+00 80 # length
+12 34 56 78 # xid
+
+fe dc ba 98 76 54 32 10 # cookie
+
+ff 00 ff 00 ff 00 ff 00 # cookie_mask
+
+03 # table_id
+04 # _command
+00 05 # idle_timeout
+00 0a # hard_timeout
+17 70 # priority
+
+00 00 00 32 # buffer_id
+00 00 00 06 # out_port
+
+00 00 00 08 # out_group
+00 00 # flags
+00 00 # pad
+
+00 01 # match.type
+00 3F # match.length # 59 bytes OXMs + 4 bytes match header
+
+80 00 01 08 # match.oxm_list[0].type_len - IN_PORT
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+
+80 00 0A 02 # match.oxm_list[1].type_len - ETH_TYPE
+86 DD # match.oxm_list[1].value - ETH_TYPE = IPv6
+
+80 00 14 01 # match.oxm_list[2].type_len - IP Proto
+06 # match.oxm_list[2].value = IP_PROTO = TCP
+
+80 00 35 20 # match.oxm_list[3].type_len - IPV6_SRC
+1C CA FE 1C B1 10 1C 00 00 28 00 00 00 00 00 00 # match.oxm_list[3].value
+FF FF FF FF FF F0 FF FF 1C 2C 3C 00 00 00 00 00 # match.oxm_list[3].mask
+
+00 # match.pad
+
+00 01 # instructions[0].type
+00 08 # instructions[0].length
+04 # instructions[0].table_id
+00 00 00 # pad
+
+00 01 # instructions[1].type
+00 08 # instructions[1].length
+07 # instructions[1].table_id
+00 00 00 # pad
+-- python
+ofp.message.flow_delete_strict(
+    xid=0x12345678,
+    cookie=0xFEDCBA9876543210,
+    cookie_mask=0xFF00FF00FF00FF00,
+    table_id=3,
+    idle_timeout=5,
+    hard_timeout=10,
+    priority=6000,
+    buffer_id=50,
+    out_port=6,
+    out_group=8,
+    flags=0,
+    match=ofp.match(oxm_list=[
+        ofp.oxm.in_port_masked(value=4, value_mask=5),
+        ofp.oxm.eth_type(value=0x86dd),
+        ofp.oxm.ip_proto(value=6),
+        ofp.oxm.ipv6_src_masked(
+            value     ='\x1C\xCA\xFE\x1C\xB1\x10\x1C\x00\x00\x28\x00\x00\x00\x00\x00\x00',
+            value_mask='\xFF\xFF\xFF\xFF\xFF\xF0\xFF\xFF\x1C\x2C\x3C\x00\x00\x00\x00\x00')
+        ]),
+    instructions=[
+        ofp.instruction.goto_table(table_id=4),
+        ofp.instruction.goto_table(table_id=7)])
+-- java
+builder.setXid(0x12345678)
+    .setCookie(U64.parseHex("FEDCBA9876543210"))
+    .setCookieMask(U64.parseHex("FF00FF00FF00FF00"))
+    .setTableId((byte) 3)
+    .setIdleTimeout(5)
+    .setHardTimeout(10)
+    .setPriority(6000)
+    .setBufferId(50)
+    .setOutPort(OFPort.of(6))
+    .setOutGroup(8)
+    .setFlags(0)
+    .setMatch(
+        factory.buildMatchV3()
+            .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
+            .setExact(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6)
+            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setMasked(MatchField.IPV6_SRC, 
+                       IPv6.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
+                       IPv6.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
+        	.build()
+    )
+    .setInstructions(
+        ImmutableList.<OFInstruction>of(
+        	factory.instructions().gotoTable((short)4),
+        	factory.instructions().gotoTable((short)7)
+        )
+    );
diff --git a/test_data/of13/flow_modify.data b/test_data/of13/flow_modify.data
new file mode 100644
index 0000000..8218b96
--- /dev/null
+++ b/test_data/of13/flow_modify.data
@@ -0,0 +1,102 @@
+-- binary
+04 0e # version, type
+00 80 # length
+12 34 56 78 # xid
+
+fe dc ba 98 76 54 32 10 # cookie
+
+ff 00 ff 00 ff 00 ff 00 # cookie_mask
+
+03 # table_id
+01 # _command
+00 05 # idle_timeout
+00 0a # hard_timeout
+17 70 # priority
+
+00 00 00 32 # buffer_id
+00 00 00 06 # out_port
+
+00 00 00 08 # out_group
+00 00 # flags
+00 00 # pad
+
+00 01 # match.type
+00 3F # match.length # 59 bytes OXMs + 4 bytes match header
+
+80 00 01 08 # match.oxm_list[0].type_len - IN_PORT
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+
+80 00 0A 02 # match.oxm_list[1].type_len - ETH_TYPE
+86 DD # match.oxm_list[1].value - ETH_TYPE = IPv6
+
+80 00 14 01 # match.oxm_list[2].type_len - IP Proto
+06 # match.oxm_list[2].value = IP_PROTO = TCP
+
+80 00 35 20 # match.oxm_list[3].type_len - IPV6_SRC
+1C CA FE 1C B1 10 1C 00 00 28 00 00 00 00 00 00 # match.oxm_list[3].value
+FF FF FF FF FF F0 FF FF 1C 2C 3C 00 00 00 00 00 # match.oxm_list[3].mask
+
+00 # match.pad
+
+00 01 # instructions[0].type
+00 08 # instructions[0].length
+04 # instructions[0].table_id
+00 00 00 # pad
+
+00 01 # instructions[1].type
+00 08 # instructions[1].length
+07 # instructions[1].table_id
+00 00 00 # pad
+-- python
+ofp.message.flow_modify(
+    xid=0x12345678,
+    cookie=0xFEDCBA9876543210,
+    cookie_mask=0xFF00FF00FF00FF00,
+    table_id=3,
+    idle_timeout=5,
+    hard_timeout=10,
+    priority=6000,
+    buffer_id=50,
+    out_port=6,
+    out_group=8,
+    flags=0,
+    match=ofp.match(oxm_list=[
+        ofp.oxm.in_port_masked(value=4, value_mask=5),
+        ofp.oxm.eth_type(value=0x86dd),
+        ofp.oxm.ip_proto(value=6),
+        ofp.oxm.ipv6_src_masked(
+            value     ='\x1C\xCA\xFE\x1C\xB1\x10\x1C\x00\x00\x28\x00\x00\x00\x00\x00\x00',
+            value_mask='\xFF\xFF\xFF\xFF\xFF\xF0\xFF\xFF\x1C\x2C\x3C\x00\x00\x00\x00\x00')
+        ]),
+    instructions=[
+        ofp.instruction.goto_table(table_id=4),
+        ofp.instruction.goto_table(table_id=7)])
+-- java
+builder.setXid(0x12345678)
+    .setCookie(U64.parseHex("FEDCBA9876543210"))
+    .setCookieMask(U64.parseHex("FF00FF00FF00FF00"))
+    .setTableId((byte) 3)
+    .setIdleTimeout(5)
+    .setHardTimeout(10)
+    .setPriority(6000)
+    .setBufferId(50)
+    .setOutPort(OFPort.of(6))
+    .setOutGroup(8)
+    .setFlags(0)
+    .setMatch(
+        factory.buildMatchV3()
+            .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
+            .setExact(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6)
+            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setMasked(MatchField.IPV6_SRC, 
+                       IPv6.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
+                       IPv6.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
+        	.build()
+    )
+    .setInstructions(
+        ImmutableList.<OFInstruction>of(
+        	factory.instructions().gotoTable((short)4),
+        	factory.instructions().gotoTable((short)7)
+        )
+    );
diff --git a/test_data/of13/flow_modify_strict.data b/test_data/of13/flow_modify_strict.data
new file mode 100644
index 0000000..3f0a074
--- /dev/null
+++ b/test_data/of13/flow_modify_strict.data
@@ -0,0 +1,102 @@
+-- binary
+04 0e # version, type
+00 80 # length
+12 34 56 78 # xid
+
+fe dc ba 98 76 54 32 10 # cookie
+
+ff 00 ff 00 ff 00 ff 00 # cookie_mask
+
+03 # table_id
+02 # _command
+00 05 # idle_timeout
+00 0a # hard_timeout
+17 70 # priority
+
+00 00 00 32 # buffer_id
+00 00 00 06 # out_port
+
+00 00 00 08 # out_group
+00 00 # flags
+00 00 # pad
+
+00 01 # match.type
+00 3F # match.length # 59 bytes OXMs + 4 bytes match header
+
+80 00 01 08 # match.oxm_list[0].type_len - IN_PORT
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+
+80 00 0A 02 # match.oxm_list[1].type_len - ETH_TYPE
+86 DD # match.oxm_list[1].value - ETH_TYPE = IPv6
+
+80 00 14 01 # match.oxm_list[2].type_len - IP Proto
+06 # match.oxm_list[2].value = IP_PROTO = TCP
+
+80 00 35 20 # match.oxm_list[3].type_len - IPV6_SRC
+1C CA FE 1C B1 10 1C 00 00 28 00 00 00 00 00 00 # match.oxm_list[3].value
+FF FF FF FF FF F0 FF FF 1C 2C 3C 00 00 00 00 00 # match.oxm_list[3].mask
+
+00 # match.pad
+
+00 01 # instructions[0].type
+00 08 # instructions[0].length
+04 # instructions[0].table_id
+00 00 00 # pad
+
+00 01 # instructions[1].type
+00 08 # instructions[1].length
+07 # instructions[1].table_id
+00 00 00 # pad
+-- python
+ofp.message.flow_modify_strict(
+    xid=0x12345678,
+    cookie=0xFEDCBA9876543210,
+    cookie_mask=0xFF00FF00FF00FF00,
+    table_id=3,
+    idle_timeout=5,
+    hard_timeout=10,
+    priority=6000,
+    buffer_id=50,
+    out_port=6,
+    out_group=8,
+    flags=0,
+    match=ofp.match(oxm_list=[
+        ofp.oxm.in_port_masked(value=4, value_mask=5),
+        ofp.oxm.eth_type(value=0x86dd),
+        ofp.oxm.ip_proto(value=6),
+        ofp.oxm.ipv6_src_masked(
+            value     ='\x1C\xCA\xFE\x1C\xB1\x10\x1C\x00\x00\x28\x00\x00\x00\x00\x00\x00',
+            value_mask='\xFF\xFF\xFF\xFF\xFF\xF0\xFF\xFF\x1C\x2C\x3C\x00\x00\x00\x00\x00')
+        ]),
+    instructions=[
+        ofp.instruction.goto_table(table_id=4),
+        ofp.instruction.goto_table(table_id=7)])
+-- java
+builder.setXid(0x12345678)
+    .setCookie(U64.parseHex("FEDCBA9876543210"))
+    .setCookieMask(U64.parseHex("FF00FF00FF00FF00"))
+    .setTableId((byte) 3)
+    .setIdleTimeout(5)
+    .setHardTimeout(10)
+    .setPriority(6000)
+    .setBufferId(50)
+    .setOutPort(OFPort.of(6))
+    .setOutGroup(8)
+    .setFlags(0)
+    .setMatch(
+        factory.buildMatchV3()
+            .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
+            .setExact(MatchField.ETH_TYPE, EthType.ETH_TYPE_IPv6)
+            .setExact(MatchField.IP_PROTO, IpProtocol.IP_PROTO_TCP)
+            .setMasked(MatchField.IPV6_SRC, 
+                       IPv6.of(0x1CCAFE1CB1101C00l, 0x0028000000000000l),
+                       IPv6.of(0xFFFFFFFFFFF0FFFFl, 0x1C2C3C0000000000l))
+        	.build()
+    )
+    .setInstructions(
+        ImmutableList.<OFInstruction>of(
+        	factory.instructions().gotoTable((short)4),
+        	factory.instructions().gotoTable((short)7)
+        )
+    );
diff --git a/test_data/of13/flow_removed.data b/test_data/of13/flow_removed.data
index 0a24993..b6d73be 100644
--- a/test_data/of13/flow_removed.data
+++ b/test_data/of13/flow_removed.data
@@ -14,11 +14,11 @@
 00 00 00 00 00 00 00 02 # byte_count
 00 01 # match.type
 00 16 # match.length
-80 00 2A 02 # match.oxm_list[0].type_len
-00 01 # match.oxm_list[0].value
-80 00 01 08 # match.oxm_list[1].type_len
-00 00 00 04 # match.oxm_list[1].value
-00 00 00 05 # match.oxm_list[1].mask
+80 00 01 08 # match.oxm_list[0].type_len - IN_PORT
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+80 00 2A 02 # match.oxm_list[1].type_len - ARP_OP
+00 01 # match.oxm_list[1].value
 00 00 # match.pad
 -- python
 ofp.message.flow_removed(
@@ -34,5 +34,6 @@
     packet_count=1,
     byte_count=2,
     match=ofp.match(oxm_list=[
-        ofp.oxm.arp_op(value=1),
-        ofp.oxm.in_port_masked(value=4, value_mask=5)]))
+        ofp.oxm.in_port_masked(value=4, value_mask=5),
+        ofp.oxm.arp_op(value=1)
+    ]))
diff --git a/test_data/of13/match_v3.data b/test_data/of13/match_v3.data
new file mode 100644
index 0000000..f8dd9b5
--- /dev/null
+++ b/test_data/of13/match_v3.data
@@ -0,0 +1,33 @@
+-- binary
+00 01 # type
+00 3C # length
+80 00 # oxm_list[0].class
+05 10 # oxm_list[0].type_len - METADATA
+FE DC BA 98 12 14 12 10 # oxm_list[0].value
+FF FF FF FF 12 34 56 78 # oxm_list[0].mask
+80 00 # oxm_list[1].class
+08 06 # oxm_list[1].type_len - ETH_SRC
+01 02 03 04 05 06 # oxm_list[1].value
+80 00 # oxm_list[2].class
+20 02 # oxm_list[2].type_len - UDP_DST
+00 35 # oxm_list[2].value
+80 00 # oxm_list[3].class
+36 10 # oxm_list[4].type_len - IPV6_DST
+12 12 12 12 12 12 12 12 # oxm_list[4].value
+12 12 12 12 12 12 12 12 # ...
+00 00 00 00 # pad
+-- python
+ofp.match([
+    ofp.oxm.metadata_masked(0xFEDCBA9812141210, 0xFFFFFFFF12345678),
+    ofp.oxm.eth_src([1,2,3,4,5,6]),
+    ofp.oxm.udp_dst(53),
+    ofp.oxm.ipv6_dst("\x12" * 16),
+])
+-- java
+builder
+       .setMasked(MatchField.METADATA, OFMetadata.ofRaw(0xFEDCBA9812141210l), OFMetadata.ofRaw(0xFFFFFFFF12345678l))
+       .setExact(MatchField.ETH_SRC, MacAddress.of(new byte[] {1,2,3,4,5,6}))
+       .setExact(MatchField.UDP_DST, TransportPort.of(53))
+       .setExact(MatchField.IPV6_DST, IPv6.of(new byte[] { 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 
+                                                           0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12 }))
+                                                           
\ No newline at end of file
diff --git a/test_data/of13/packet_in.data b/test_data/of13/packet_in.data
index 951f212..1ec0422 100644
--- a/test_data/of13/packet_in.data
+++ b/test_data/of13/packet_in.data
@@ -9,11 +9,11 @@
 fe dc ba 98 76 54 32 10 # cookie
 00 01 # match.type
 00 16 # match.length
-80 00 2A 02 # match.oxm_list[0].type_len
-00 01 # match.oxm_list[0].value
-80 00 01 08 # match.oxm_list[1].type_len
-00 00 00 04 # match.oxm_list[1].value
-00 00 00 05 # match.oxm_list[1].mask
+80 00 01 08 # match.oxm_list[0].type_len - Input Port
+00 00 00 04 # match.oxm_list[0].value
+00 00 00 05 # match.oxm_list[0].mask
+80 00 2A 02 # match.oxm_list[1].type_len - ARP OpCode
+00 01 # match.oxm_list[1].value
 00 00 # match.pad
 00 00 # pad
 61 62 63 # data
@@ -26,12 +26,11 @@
     table_id=20,
     cookie=0xFEDCBA9876543210,
     match=ofp.match(oxm_list=[
-        ofp.oxm.arp_op(value=1),
-        ofp.oxm.in_port_masked(value=4, value_mask=5)]),
+        ofp.oxm.in_port_masked(value=4, value_mask=5),
+        ofp.oxm.arp_op(value=1)
+        ]),
     data="abc")
 -- java
-OFOxms oxms = factory.oxms();
-
 builder
    .setXid(0x12345678)
    .setBufferId(100)
@@ -40,12 +39,10 @@
    .setTableId((byte) 20)
    .setCookie(U64.parseHex("FEDCBA9876543210"))
    .setMatch(
-        factory.buildMatchV3().setOxmList(
-            OFOxmList.of(
-                oxms.arpOp(ArpOpcode.ARP_OPCODE_REQUEST),
-                oxms.inPortMasked(OFPort.of(4), OFPort.of(5))
-            )
-        ).build()
+        factory.buildMatchV3()
+            .setMasked(MatchField.IN_PORT, OFPort.of(4), OFPort.of(5))
+            .setExact(MatchField.ARP_OP, ArpOpcode.ARP_OPCODE_REQUEST)
+        	.build()
     )
     .setData(new byte[] { 97, 98, 99 } );