Merge branch 'master' of github.com:floodlight/loxigen
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 5e5779e..0797dcd 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/Match.java b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
index cdb34e5..3fc5527 100644
--- a/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
+++ b/java_gen/pre-written/src/main/java/org/openflow/protocol/match/Match.java
@@ -142,7 +142,21 @@
      *
      * @author Yotam Harchol (yotam.harchol@bigswitch.com)
      */
-    interface Builder extends Match {
+    interface Builder {
+        public <F extends OFValueType<F>> F get(MatchField<F> field) throws UnsupportedOperationException;
+
+        public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field) throws UnsupportedOperationException;
+
+        public boolean supports(MatchField<?> field);
+
+        public boolean supportsMasked(MatchField<?> field) throws UnsupportedOperationException;
+
+        public boolean isExact(MatchField<?> field) throws UnsupportedOperationException;
+
+        public boolean isFullyWildcarded(MatchField<?> field) throws UnsupportedOperationException;
+
+        public boolean isPartiallyMasked(MatchField<?> field) throws UnsupportedOperationException;
+
         /**
          * Sets a specific exact value for a field.
          *
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/pre-written/src/test/java/org/openflow/types/IPv4Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
index a5ac1be..8125b04 100644
--- a/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/IPv4Test.java
@@ -7,7 +7,6 @@
 import org.jboss.netty.buffer.ChannelBuffers;
 import org.junit.Test;
 import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortRead;
 
 public class IPv4Test {
     byte[][] testAddresses = new byte[][] {
@@ -42,21 +41,21 @@
             "1.x.3.4",
             "1.2x.3.4"
     };
-    
+
     String[] ipsWithMask = {
                             "1.2.3.4/24",
                             "192.168.130.140/255.255.192.0",
                             "127.0.0.1/8",
                             "8.8.8.8",
     };
-    
+
     boolean[] hasMask = {
                          true,
                          true,
                          true,
                          false
     };
-    
+
     byte[][][] ipsWithMaskValues = {
                              new byte[][] { new byte[] { (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00 } },
                              new byte[][] { new byte[] { (byte)0xC0, (byte)0xA8, (byte)0x82, (byte)0x8C }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xC0, (byte)0x00 } },
@@ -86,7 +85,7 @@
     }
 
     @Test
-    public void testReadFrom() throws OFParseError, OFShortRead {
+    public void testReadFrom() throws OFParseError {
         for(int i=0; i < testAddresses.length; i++ ) {
             IPv4 ip = IPv4.read4Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
             assertEquals(testInts[i], ip.getInt());
@@ -97,7 +96,7 @@
 
 
     @Test
-    public void testInvalidIPs() throws OFParseError, OFShortRead {
+    public void testInvalidIPs() throws OFParseError {
         for(String invalid : invalidIPs) {
             try {
                 IPv4.of(invalid);
@@ -107,9 +106,9 @@
             }
         }
     }
-    
+
     @Test
-    public void testOfMasked() throws OFParseError, OFShortRead {
+    public void testOfMasked() throws OFParseError {
         for (int i = 0; i < ipsWithMask.length; i++) {
             IPv4WithMask value = IPv4WithMask.of(ipsWithMask[i]);
             if (!hasMask[i]) {
@@ -122,7 +121,7 @@
                 for (int j = 0; j < ipBytes.length; j++) {
                     ipBytes[j] &= ipsWithMaskValues[i][1][j];
                 }
-                
+
                 assertArrayEquals(ipBytes, value.getValue().getBytes());
                 assertArrayEquals(ipsWithMaskValues[i][1], value.getMask().getBytes());
             }
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java b/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
index 71ab28e..352b8bc 100644
--- a/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/IPv6Test.java
@@ -11,7 +11,6 @@
 import org.jboss.netty.buffer.ChannelBuffers;
 import org.junit.Test;
 import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortRead;
 
 public class IPv6Test {
 
@@ -21,33 +20,33 @@
             "ffe0::",
             "1:2:3:4:5:6:7:8"
     };
-    
+
     String[] ipsWithMask = {
                             "1::1/80",
                             "1:2:3:4::/ffff:ffff:ffff:ff00::",
                             "ffff:ffee:1::/ff00:ff00:ff00:ff00::",
                             "8:8:8:8:8:8:8:8",
     };
-    
+
     byte[][] masks = {
-                    new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 
-                                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 
-                                 (byte)0xff, (byte)0xff, (byte)0x00, (byte)0x00, 
+                    new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
+                                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
+                                 (byte)0xff, (byte)0xff, (byte)0x00, (byte)0x00,
                                  (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
-                    new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 
-                                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x00, 
-                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+                    new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
+                                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x00,
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
                                  (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
-                    new byte[] { (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00, 
-                                 (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00, 
-                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+                    new byte[] { (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00,
+                                 (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00,
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
                                  (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
-                    new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
-                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
-                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+                    new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                                 (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
                                  (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }
     };
-    
+
     boolean[] hasMask = {
                          true,
                          true,
@@ -70,11 +69,11 @@
 
                 byte[] address = inetAddress.getAddress();
                 assertEquals(address.length, value.getValue().getBytes().length);
-                
+
                 for (int j = 0; j < address.length; j++) {
                     address[j] &= masks[i][j];
                 }
-                
+
                 assertArrayEquals(value.getValue().getBytes(), address);
                 assertArrayEquals(masks[i], value.getMask().getBytes());
             }
@@ -104,7 +103,7 @@
     }
 
     @Test
-    public void testReadFrom() throws OFParseError, OFShortRead, UnknownHostException {
+    public void testReadFrom() throws OFParseError, UnknownHostException {
         for(int i=0; i < testStrings.length; i++ ) {
             byte[] bytes = Inet6Address.getByName(testStrings[i]).getAddress();
             IPv6 ip = IPv6.read16Bytes(ChannelBuffers.copiedBuffer(bytes));
@@ -126,7 +125,7 @@
     };
 
     @Test
-    public void testInvalidIPs() throws OFParseError, OFShortRead {
+    public void testInvalidIPs() throws OFParseError {
         for(String invalid : invalidIPs) {
             try {
                 IPv6.of(invalid);
@@ -138,7 +137,7 @@
     }
 
     @Test
-    public void testZeroCompression() throws OFParseError, OFShortRead {
+    public void testZeroCompression() throws OFParseError {
         assertEquals("::", IPv6.of("::").toString(true, false));
         assertEquals("0:0:0:0:0:0:0:0", IPv6.of("::").toString(false, false));
         assertEquals("0000:0000:0000:0000:0000:0000:0000:0000", IPv6.of("::").toString(false, true));
diff --git a/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java b/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java
index 78728e1..2be3046 100644
--- a/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/openflow/types/MacAddressTest.java
@@ -9,7 +9,6 @@
 import org.jboss.netty.buffer.ChannelBuffers;
 import org.junit.Test;
 import org.openflow.exceptions.OFParseError;
-import org.openflow.exceptions.OFShortRead;
 
 public class MacAddressTest {
     byte[][] testAddresses = new byte[][] {
@@ -62,7 +61,7 @@
     }
 
     @Test
-    public void testReadFrom() throws OFParseError, OFShortRead {
+    public void testReadFrom() throws OFParseError {
         for(int i=0; i < testAddresses.length; i++ ) {
             MacAddress ip = MacAddress.read6Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
             assertEquals(testInts[i], ip.getLong());
@@ -73,7 +72,7 @@
 
 
     @Test
-    public void testInvalidMacss() throws OFParseError, OFShortRead {
+    public void testInvalidMacss() throws OFParseError {
         for(String invalid : invalidMacs) {
             try {
                 MacAddress.of(invalid);
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
index ba739bc..6570df8 100644
--- a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
+++ b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
@@ -69,13 +69,3 @@
         // FIXME yotam - please replace with real implementation
         return null;
     }
-
-    @Override
-    public Builder createBuilder() {
-        return this;
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer bb) {
-        // FIXME yotam - please replace with real implementation        
-    }
diff --git a/java_gen/templates/custom/OFMatchV2Ver11.Builder.java b/java_gen/templates/custom/OFMatchV2Ver11.Builder.java
index ba739bc..6570df8 100644
--- a/java_gen/templates/custom/OFMatchV2Ver11.Builder.java
+++ b/java_gen/templates/custom/OFMatchV2Ver11.Builder.java
@@ -69,13 +69,3 @@
         // FIXME yotam - please replace with real implementation
         return null;
     }
-
-    @Override
-    public Builder createBuilder() {
-        return this;
-    }
-
-    @Override
-    public void writeTo(ChannelBuffer bb) {
-        // FIXME yotam - please replace with real implementation        
-    }
diff --git a/java_gen/templates/custom/OFMatchV3Ver12.Builder.java b/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
index ba739bc..3fae367 100644
--- a/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
+++ b/java_gen/templates/custom/OFMatchV3Ver12.Builder.java
@@ -1,81 +1,106 @@
 
-    @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;
-    }
-
-    @Override
-    public <F extends OFValueType<F>> Match.Builder setMasked(
-            MatchField<F> field, F value, F mask) {
-        // FIXME yotam - please replace with real implementation
-        return null;
-    }
-
-    @Override
-    public <F extends OFValueType<F>> Match.Builder setMasked(
-            MatchField<F> field, Masked<F> valueWithMask) {
-        // FIXME yotam - please replace with real implementation
-        return null;
-    }
-
-    @Override
-    public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
-        // FIXME yotam - please replace with real implementation
-        return null;
-    }
-
-    @Override
-    public Builder createBuilder() {
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValue(value, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
         return this;
     }
 
     @Override
-    public void writeTo(ChannelBuffer bb) {
-        // FIXME yotam - please replace with real implementation        
+    public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
+            MatchField<F> field, F value, F mask) {
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValueAndMask(value, mask, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
+    }
+
+    @Override
+    public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
+            MatchField<F> field, Masked<F> valueWithMask) {
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromMasked(valueWithMask, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
+    }
+
+    @Override
+    public synchronized <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+        initBuilder();
+        this.oxmListBuilder.unset(field);
+        updateOxmList();
+        return this;
     }
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..48f8b70 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
@@ -1,82 +1,107 @@
 
-    @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;
-    }
-
-    @Override
-    public <F extends OFValueType<F>> Match.Builder setMasked(
-            MatchField<F> field, F value, F mask) {
-        // FIXME yotam - please replace with real implementation
-        return null;
-    }
-
-    @Override
-    public <F extends OFValueType<F>> Match.Builder setMasked(
-            MatchField<F> field, Masked<F> valueWithMask) {
-        // FIXME yotam - please replace with real implementation
-        return null;
-    }
-
-    @Override
-    public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
-        // FIXME yotam - please replace with real implementation
-        return null;
-    }
-
-    @Override
-    public Builder createBuilder() {
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValue(value, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
         return this;
     }
 
     @Override
-    public void writeTo(ChannelBuffer bb) {
-        // FIXME yotam - please replace with real implementation        
+    public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
+            MatchField<F> field, F value, F mask) {
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValueAndMask(value, mask, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
+    }
+
+    @Override
+    public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
+            MatchField<F> field, Masked<F> valueWithMask) {
+        initBuilder();
+        OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromMasked(valueWithMask, field);
+        this.oxmListBuilder.set(oxm);
+        updateOxmList();
+        return this;
+    }
+
+    @Override
+    public synchronized <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+        initBuilder();
+        this.oxmListBuilder.unset(field);
+        updateOxmList();
+        return this;
     }
 
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/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index d78d5bd..5483ff4 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -335,7 +335,7 @@
     uint8_t type == 4;
     uint16_t length;
     uint32_t xid;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     uint32_t subtype;
     of_octets_t data;
 };
@@ -525,7 +525,7 @@
 struct of_action_experimenter : of_action {
     uint16_t type == 65535;
     uint16_t len;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
@@ -919,7 +919,7 @@
     uint32_t xid;
     uint16_t stats_type == 0xffff;
     uint16_t flags;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
@@ -930,7 +930,7 @@
     uint32_t xid;
     uint16_t stats_type == 0xffff;
     uint16_t flags;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index 1047127..a1127b1 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -443,7 +443,7 @@
     uint8_t type == 4;
     uint16_t length;
     uint32_t xid;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     uint32_t subtype;
     of_octets_t data;
 };
@@ -742,7 +742,7 @@
 struct of_action_experimenter : of_action {
     uint16_t type == 65535;
     uint16_t len;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
@@ -837,7 +837,7 @@
 struct of_instruction_experimenter : of_instruction {
     uint16_t type == 65535;
     uint16_t len;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
@@ -1327,7 +1327,7 @@
     uint16_t stats_type == 0xffff;
     uint16_t flags;
     pad(4);
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     pad(4);
     of_octets_t data;
 };
@@ -1340,7 +1340,7 @@
     uint16_t stats_type == 0xffff;
     uint16_t flags;
     pad(4);
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     pad(4);
     of_octets_t data;
 };
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index e4c8ec2..bfa9a64 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -483,7 +483,7 @@
     uint8_t type == 4;
     uint16_t length;
     uint32_t xid;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     uint32_t subtype;
     of_octets_t data;
 };
@@ -699,7 +699,7 @@
 struct of_action_experimenter : of_action {
     uint16_t type == 65535;
     uint16_t len;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
@@ -753,7 +753,7 @@
 struct of_instruction_experimenter : of_instruction {
     uint16_t type == 65535;
     uint16_t len;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
@@ -1317,7 +1317,7 @@
     uint16_t stats_type == 0xffff;
     uint16_t flags;
     pad(4);
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     uint32_t subtype;
     of_octets_t data;
 };
@@ -1330,7 +1330,7 @@
     uint16_t stats_type == 0xffff;
     uint16_t flags;
     pad(4);
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     uint32_t subtype;
     of_octets_t data;
 };
@@ -1363,7 +1363,7 @@
     uint16_t type == 65535;
     uint16_t len;
     pad(4);
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     pad(4);
     of_octets_t data;
 };
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index b9c5475..119e7a4 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -608,7 +608,7 @@
     uint8_t type == 4;
     uint16_t length;
     uint32_t xid;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     uint32_t subtype;
     of_octets_t data;
 };
@@ -833,7 +833,7 @@
 struct of_action_experimenter : of_action {
     uint16_t type == 65535;
     uint16_t len;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
@@ -905,7 +905,7 @@
 struct of_instruction_experimenter : of_instruction {
     uint16_t type == 65535;
     uint16_t len;
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     of_octets_t data;
 };
 
@@ -1177,7 +1177,8 @@
     uint16_t priority;
     uint16_t idle_timeout;
     uint16_t hard_timeout;
-    pad(6);
+    uint16_t flags;
+    pad(4);
     uint64_t cookie;
     uint64_t packet_count;
     uint64_t byte_count;
@@ -1770,7 +1771,7 @@
 };
 
 struct of_experimenter_multipart_header {
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     uint32_t subtype;
 };
 
@@ -1802,7 +1803,7 @@
     uint16_t type == 65535;
     uint16_t len;
     pad(4);
-    uint32_t experimenter;
+    uint32_t experimenter == ?;
     pad(4);
     of_octets_t data;
 };
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 6570938..540d212 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -54,13 +54,10 @@
 # Create intermediate representation, extended from the LOXI IR
 # HACK the oftype member attribute is replaced with an OFType instance
 def build_ofclasses(version):
-    blacklist = ["of_experimenter", "of_action_experimenter"]
     ofclasses = []
     for ofclass in of_g.ir[version].classes:
         cls = ofclass.name
-        if type_maps.class_is_virtual(cls):
-            continue
-        if cls in blacklist:
+        if ofclass.virtual:
             continue
 
         members = []
diff --git a/py_gen/templates/message.py b/py_gen/templates/message.py
index 6754b94..7158545 100644
--- a/py_gen/templates/message.py
+++ b/py_gen/templates/message.py
@@ -226,11 +226,6 @@
     const.OFPST_TABLE : table_stats_reply.unpack,
     const.OFPST_PORT : port_stats_reply.unpack,
     const.OFPST_QUEUE : queue_stats_reply.unpack,
-:: if version < of_g.VERSION_1_1:
-    const.OFPST_VENDOR : experimenter_stats_reply.unpack,
-:: else:
-    const.OFPST_EXPERIMENTER : experimenter_stats_reply.unpack,
-:: #endif
 :: if version >= of_g.VERSION_1_1:
     const.OFPST_GROUP : group_stats_reply.unpack,
     const.OFPST_GROUP_DESC : group_desc_stats_reply.unpack,
@@ -247,11 +242,6 @@
     const.OFPST_TABLE : table_stats_request.unpack,
     const.OFPST_PORT : port_stats_request.unpack,
     const.OFPST_QUEUE : queue_stats_request.unpack,
-:: if version < of_g.VERSION_1_1:
-    const.OFPST_VENDOR : experimenter_stats_request.unpack,
-:: else:
-    const.OFPST_EXPERIMENTER : experimenter_stats_request.unpack,
-:: #endif
 :: if version >= of_g.VERSION_1_1:
     const.OFPST_GROUP : group_stats_request.unpack,
     const.OFPST_GROUP_DESC : group_desc_stats_request.unpack,
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 } );