Added cubby-holes for new projects.
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver10/OFMatchV1Ver10.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver10/OFMatchV1Ver10.java
new file mode 100644
index 0000000..14e829c
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver10/OFMatchV1Ver10.java
@@ -0,0 +1,2434 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_class.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol.ver10;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.List;
+import com.google.common.collect.ImmutableList;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.hash.Funnel;
+
+class OFMatchV1Ver10 implements OFMatchV1 {
+    private static final Logger logger = LoggerFactory.getLogger(OFMatchV1Ver10.class);
+    // version: 1.0
+    final static byte WIRE_VERSION = 1;
+    final static int LENGTH = 40;
+
+        private final static int DEFAULT_WILDCARDS = OFFlowWildcardsSerializerVer10.ALL_VAL;
+        private final static OFPort DEFAULT_IN_PORT = OFPort.ZERO;
+        private final static MacAddress DEFAULT_ETH_SRC = MacAddress.NONE;
+        private final static MacAddress DEFAULT_ETH_DST = MacAddress.NONE;
+        private final static OFVlanVidMatch DEFAULT_VLAN_VID = OFVlanVidMatch.NONE;
+        private final static VlanPcp DEFAULT_VLAN_PCP = VlanPcp.NONE;
+        private final static EthType DEFAULT_ETH_TYPE = EthType.NONE;
+        private final static IpDscp DEFAULT_IP_DSCP = IpDscp.NONE;
+        private final static IpProtocol DEFAULT_IP_PROTO = IpProtocol.NONE;
+        private final static IPv4Address DEFAULT_IPV4_SRC = IPv4Address.NONE;
+        private final static IPv4Address DEFAULT_IPV4_DST = IPv4Address.NONE;
+        private final static TransportPort DEFAULT_TCP_SRC = TransportPort.NONE;
+        private final static TransportPort DEFAULT_TCP_DST = TransportPort.NONE;
+
+    // OF message fields
+    private final int wildcards;
+    private final OFPort inPort;
+    private final MacAddress ethSrc;
+    private final MacAddress ethDst;
+    private final OFVlanVidMatch vlanVid;
+    private final VlanPcp vlanPcp;
+    private final EthType ethType;
+    private final IpDscp ipDscp;
+    private final IpProtocol ipProto;
+    private final IPv4Address ipv4Src;
+    private final IPv4Address ipv4Dst;
+    private final TransportPort tcpSrc;
+    private final TransportPort tcpDst;
+//
+    // Immutable default instance
+    final static OFMatchV1Ver10 DEFAULT = new OFMatchV1Ver10(
+        DEFAULT_WILDCARDS, DEFAULT_IN_PORT, DEFAULT_ETH_SRC, DEFAULT_ETH_DST, DEFAULT_VLAN_VID, DEFAULT_VLAN_PCP, DEFAULT_ETH_TYPE, DEFAULT_IP_DSCP, DEFAULT_IP_PROTO, DEFAULT_IPV4_SRC, DEFAULT_IPV4_DST, DEFAULT_TCP_SRC, DEFAULT_TCP_DST
+    );
+
+    // package private constructor - used by readers, builders, and factory
+    OFMatchV1Ver10(int wildcards, OFPort inPort, MacAddress ethSrc, MacAddress ethDst, OFVlanVidMatch vlanVid, VlanPcp vlanPcp, EthType ethType, IpDscp ipDscp, IpProtocol ipProto, IPv4Address ipv4Src, IPv4Address ipv4Dst, TransportPort tcpSrc, TransportPort tcpDst) {
+        this.wildcards = wildcards;
+        this.inPort = inPort;
+        this.ethSrc = ethSrc;
+        this.ethDst = ethDst;
+        this.vlanVid = vlanVid;
+        this.vlanPcp = vlanPcp;
+        this.ethType = ethType;
+        this.ipDscp = ipDscp;
+        this.ipProto = ipProto;
+        this.ipv4Src = ipv4Src;
+        this.ipv4Dst = ipv4Dst;
+        this.tcpSrc = tcpSrc;
+        this.tcpDst = tcpDst;
+    }
+
+    // Accessors for OF message fields
+    @Override
+    public int getWildcards() {
+        return wildcards;
+    }
+
+    @Override
+    public OFPort getInPort() {
+        return inPort;
+    }
+
+    @Override
+    public MacAddress getEthSrc() {
+        return ethSrc;
+    }
+
+    @Override
+    public MacAddress getEthDst() {
+        return ethDst;
+    }
+
+    @Override
+    public OFVlanVidMatch getVlanVid() {
+        return vlanVid;
+    }
+
+    @Override
+    public VlanPcp getVlanPcp() {
+        return vlanPcp;
+    }
+
+    @Override
+    public EthType getEthType() {
+        return ethType;
+    }
+
+    @Override
+    public IpDscp getIpDscp() {
+        return ipDscp;
+    }
+
+    @Override
+    public IpProtocol getIpProto() {
+        return ipProto;
+    }
+
+    @Override
+    public IPv4Address getIpv4Src() {
+        return ipv4Src;
+    }
+
+    @Override
+    public IPv4Address getIpv4Dst() {
+        return ipv4Dst;
+    }
+
+    @Override
+    public TransportPort getTcpSrc() {
+        return tcpSrc;
+    }
+
+    @Override
+    public TransportPort getTcpDst() {
+        return tcpDst;
+    }
+
+    @Override
+    public OFVersion getVersion() {
+        return OFVersion.OF_10;
+    }
+
+
+    final public static int OFPFW_ALL = ((1 << 22) - 1);
+
+    final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */
+    final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */
+    final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */
+    final public static int OFPFW_DL_DST = 1 << 3; /*
+                                                    * Ethernet destination
+                                                    * address.
+                                                    */
+    final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */
+    final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */
+    final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */
+    final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */
+
+    /*
+     * IP source address wildcard bit count. 0 is exact match, 1 ignores the
+     * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
+     * the entire field. This is the *opposite* of the usual convention where
+     * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded.
+     */
+    final public static int OFPFW_NW_SRC_SHIFT = 8;
+    final public static int OFPFW_NW_SRC_BITS = 6;
+    final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT;
+    final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT;
+
+    /* IP destination address wildcard bit count. Same format as source. */
+    final public static int OFPFW_NW_DST_SHIFT = 14;
+    final public static int OFPFW_NW_DST_BITS = 6;
+    final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT;
+    final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT;
+
+    final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */
+    final public static int OFPFW_NW_TOS = 1 << 21; /* IP ToS (DSCP field, 6bits) */
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <F extends OFValueType<F>> F get(MatchField<F> field)
+            throws UnsupportedOperationException {
+        if (isFullyWildcarded(field))
+            return null;
+        if (!field.arePrerequisitesOK(this))
+            return null;
+
+        Object result;
+        switch (field.id) {
+            case IN_PORT:
+                result = inPort;
+                break;
+            case ETH_DST:
+                result = ethDst;
+                break;
+            case ETH_SRC:
+                result = ethSrc;
+                break;
+            case ETH_TYPE:
+                result = ethType;
+                break;
+            case VLAN_VID:
+                result = vlanVid;
+                break;
+            case VLAN_PCP:
+                result = vlanPcp;
+                break;
+            case ARP_OP:
+                result = ArpOpcode.of(ipProto.getIpProtocolNumber());
+                break;
+            case ARP_SPA:
+                result = ipv4Src;
+                break;
+            case ARP_TPA:
+                result = ipv4Dst;
+                break;
+            case IP_DSCP:
+                result = ipDscp;
+                break;
+            case IP_PROTO:
+                result = ipProto;
+                break;
+            case IPV4_SRC:
+                result = ipv4Src;
+                break;
+            case IPV4_DST:
+                result = ipv4Dst;
+                break;
+            case TCP_SRC:
+                result = tcpSrc;
+                break;
+            case TCP_DST:
+                result = tcpDst;
+                break;
+            case UDP_SRC:
+                result = tcpSrc;
+                break;
+            case UDP_DST:
+                result = tcpDst;
+                break;
+            case SCTP_SRC:
+                result = tcpSrc;
+                break;
+            case SCTP_DST:
+                result = tcpDst;
+                break;
+            case ICMPV4_TYPE:
+                result = tcpSrc;
+                break;
+            case ICMPV4_CODE:
+                result = tcpDst;
+                break;
+            // NOT SUPPORTED:
+            default:
+                throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+        }
+        return (F)result;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+            throws UnsupportedOperationException {
+        if (!isPartiallyMasked(field))
+            return null;
+        if (!field.arePrerequisitesOK(this))
+            return null;
+        Object result;
+        switch (field.id) {
+            case ARP_SPA:
+            case IPV4_SRC:
+                int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
+                result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
+                break;
+            case ARP_TPA:
+            case IPV4_DST:
+                int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
+
+                result = IPv4AddressWithMask.of(ipv4Dst, IPv4Address.of(dstBitMask));
+                break;
+            default:
+                throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+        }
+        return (Masked<F>)result;
+    }
+
+    @Override
+    public boolean supports(MatchField<?> field) {
+        switch (field.id) {
+            case IN_PORT:
+            case ETH_DST:
+            case ETH_SRC:
+            case ETH_TYPE:
+            case VLAN_VID:
+            case VLAN_PCP:
+            case ARP_OP:
+            case ARP_SPA:
+            case ARP_TPA:
+            case IP_DSCP:
+            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:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public boolean supportsMasked(MatchField<?> field) {
+        switch (field.id) {
+            case ARP_SPA:
+            case ARP_TPA:
+            case IPV4_SRC:
+            case IPV4_DST:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public boolean isExact(MatchField<?> field) {
+        if (!field.arePrerequisitesOK(this))
+            return false;
+
+        switch (field.id) {
+            case IN_PORT:
+                return (this.wildcards & OFPFW_IN_PORT) == 0;
+            case ETH_DST:
+                return (this.wildcards & OFPFW_DL_DST) == 0;
+            case ETH_SRC:
+                return (this.wildcards & OFPFW_DL_SRC) == 0;
+            case ETH_TYPE:
+                return (this.wildcards & OFPFW_DL_TYPE) == 0;
+            case VLAN_VID:
+                return (this.wildcards & OFPFW_DL_VLAN) == 0;
+            case VLAN_PCP:
+                return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
+            case ARP_OP:
+                return (this.wildcards & OFPFW_NW_PROTO) == 0;
+            case ARP_SPA:
+                return this.getIpv4SrcCidrMaskLen() >= 32;
+            case ARP_TPA:
+                return this.getIpv4DstCidrMaskLen() >= 32;
+            case IP_DSCP:
+                return (this.wildcards & OFPFW_NW_TOS) == 0;
+            case IP_PROTO:
+                return (this.wildcards & OFPFW_NW_PROTO) == 0;
+            case IPV4_SRC:
+                return this.getIpv4SrcCidrMaskLen() >= 32;
+            case IPV4_DST:
+                return this.getIpv4DstCidrMaskLen() >= 32;
+            case TCP_SRC:
+                return (this.wildcards & OFPFW_TP_SRC) == 0;
+            case TCP_DST:
+                return (this.wildcards & OFPFW_TP_DST) == 0;
+            case UDP_SRC:
+                return (this.wildcards & OFPFW_TP_SRC) == 0;
+            case UDP_DST:
+                return (this.wildcards & OFPFW_TP_DST) == 0;
+            case SCTP_SRC:
+                return (this.wildcards & OFPFW_TP_SRC) == 0;
+            case SCTP_DST:
+                return (this.wildcards & OFPFW_TP_DST) == 0;
+            case ICMPV4_TYPE:
+                return (this.wildcards & OFPFW_TP_SRC) == 0;
+            case ICMPV4_CODE:
+                return (this.wildcards & OFPFW_TP_DST) == 0;
+            default:
+                throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+        }
+    }
+
+    /**
+     * Parse this match's wildcard fields and return the number of significant
+     * bits in the IP destination field. NOTE: this returns the number of bits
+     * that are fixed, i.e., like CIDR, not the number of bits that are free
+     * like OpenFlow encodes.
+     *
+     * @return A number between 0 (matches all IPs) and 32 (exact match)
+     */
+    public int getIpv4DstCidrMaskLen() {
+        return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
+                        0);
+    }
+
+    /**
+     * Parse this match's wildcard fields and return the number of significant
+     * bits in the IP destination field. NOTE: this returns the number of bits
+     * that are fixed, i.e., like CIDR, not the number of bits that are free
+     * like OpenFlow encodes.
+     *
+     * @return A number between 0 (matches all IPs) and 32 (exact match)
+     */
+    public int getIpv4SrcCidrMaskLen() {
+        return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
+                        0);
+    }
+
+
+    @Override
+    public boolean isFullyWildcarded(MatchField<?> field) {
+        if (!field.arePrerequisitesOK(this))
+            return true;
+
+        switch (field.id) {
+            case IN_PORT:
+                return (this.wildcards & OFPFW_IN_PORT) != 0;
+            case ETH_DST:
+                return (this.wildcards & OFPFW_DL_DST) != 0;
+            case ETH_SRC:
+                return (this.wildcards & OFPFW_DL_SRC) != 0;
+            case ETH_TYPE:
+                return (this.wildcards & OFPFW_DL_TYPE) != 0;
+            case VLAN_VID:
+                return (this.wildcards & OFPFW_DL_VLAN) != 0;
+            case VLAN_PCP:
+                return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
+            case ARP_OP:
+                return (this.wildcards & OFPFW_NW_PROTO) != 0;
+            case ARP_SPA:
+                return this.getIpv4SrcCidrMaskLen() <= 0;
+            case ARP_TPA:
+                return this.getIpv4DstCidrMaskLen() <= 0;
+            case IP_DSCP:
+                return (this.wildcards & OFPFW_NW_TOS) != 0;
+            case IP_PROTO:
+                return (this.wildcards & OFPFW_NW_PROTO) != 0;
+            case TCP_SRC:
+                return (this.wildcards & OFPFW_TP_SRC) != 0;
+            case TCP_DST:
+                return (this.wildcards & OFPFW_TP_DST) != 0;
+            case UDP_SRC:
+                return (this.wildcards & OFPFW_TP_SRC) != 0;
+            case UDP_DST:
+                return (this.wildcards & OFPFW_TP_DST) != 0;
+            case SCTP_SRC:
+                return (this.wildcards & OFPFW_TP_SRC) != 0;
+            case SCTP_DST:
+                return (this.wildcards & OFPFW_TP_DST) != 0;
+            case ICMPV4_TYPE:
+                return (this.wildcards & OFPFW_TP_SRC) != 0;
+            case ICMPV4_CODE:
+                return (this.wildcards & OFPFW_TP_DST) != 0;
+            case IPV4_SRC:
+                return this.getIpv4SrcCidrMaskLen() <= 0;
+            case IPV4_DST:
+                return this.getIpv4DstCidrMaskLen() <= 0;
+            default:
+                throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+        }
+    }
+
+    @Override
+    public boolean isPartiallyMasked(MatchField<?> field) {
+        if (!field.arePrerequisitesOK(this))
+            return false;
+
+        switch (field.id) {
+            case ARP_SPA:
+            case IPV4_SRC:
+                int srcCidrLen = getIpv4SrcCidrMaskLen();
+                return srcCidrLen > 0 && srcCidrLen < 32;
+            case ARP_TPA:
+            case IPV4_DST:
+                int dstCidrLen = getIpv4DstCidrMaskLen();
+                return dstCidrLen > 0 && dstCidrLen < 32;
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public Iterable<MatchField<?>> getMatchFields() {
+        ImmutableList.Builder<MatchField<?>> builder = ImmutableList.builder();
+        if ((wildcards & OFPFW_IN_PORT) == 0)
+            builder.add(MatchField.IN_PORT);
+        if ((wildcards & OFPFW_DL_VLAN) == 0)
+            builder.add(MatchField.VLAN_VID);
+        if ((wildcards & OFPFW_DL_SRC) == 0)
+            builder.add(MatchField.ETH_SRC);
+        if ((wildcards & OFPFW_DL_DST) == 0)
+            builder.add(MatchField.ETH_DST);
+        if ((wildcards & OFPFW_DL_TYPE) == 0)
+            builder.add(MatchField.ETH_TYPE);
+        if ((wildcards & OFPFW_NW_PROTO) == 0) {
+            if (ethType == EthType.ARP) {
+                builder.add(MatchField.ARP_OP);
+            } else if (ethType == EthType.IPv4) {
+                builder.add(MatchField.IP_PROTO);
+            } else {
+                throw new UnsupportedOperationException(
+                        "Unsupported Ethertype for matching on network protocol " + ethType);
+            }
+        }
+        if ((wildcards & OFPFW_TP_SRC) == 0) {
+            if (ipProto == IpProtocol.UDP) {
+                builder.add(MatchField.UDP_SRC);
+            } else if (ipProto == IpProtocol.TCP) {
+                builder.add(MatchField.TCP_SRC);
+            } else if (ipProto == IpProtocol.SCTP) {
+                builder.add(MatchField.SCTP_SRC);
+            } else {
+                throw new UnsupportedOperationException(
+                        "Unsupported IP protocol for matching on source port " + ipProto);
+            }
+        }
+        if ((wildcards & OFPFW_TP_DST) == 0) {
+            if (ipProto == IpProtocol.UDP) {
+                builder.add(MatchField.UDP_DST);
+            } else if (ipProto == IpProtocol.TCP) {
+                builder.add(MatchField.TCP_DST);
+            } else if (ipProto == IpProtocol.SCTP) {
+                builder.add(MatchField.SCTP_DST);
+            } else {
+                throw new UnsupportedOperationException(
+                        "Unsupported IP protocol for matching on destination port " + ipProto);
+            }
+        }
+        if (((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT) < 32) {
+            if (ethType == EthType.ARP) {
+                builder.add(MatchField.ARP_SPA);
+            } else if (ethType == EthType.IPv4) {
+                builder.add(MatchField.IPV4_SRC);
+            } else {
+                throw new UnsupportedOperationException(
+                        "Unsupported Ethertype for matching on source IP " + ethType);
+            }
+        }
+        if (((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT) < 32) {
+            if (ethType == EthType.ARP) {
+                builder.add(MatchField.ARP_TPA);
+            } else if (ethType == EthType.IPv4) {
+                builder.add(MatchField.IPV4_DST);
+            } else {
+                throw new UnsupportedOperationException(
+                        "Unsupported Ethertype for matching on destination IP " + ethType);
+            }
+        }
+        if ((wildcards & OFPFW_DL_VLAN_PCP) == 0)
+            builder.add(MatchField.VLAN_PCP);
+        if ((wildcards & OFPFW_NW_TOS) == 0)
+            builder.add(MatchField.IP_DSCP);
+        return builder.build();
+    }
+
+    public OFMatchV1.Builder createBuilder() {
+        return new BuilderWithParent(this);
+    }
+
+    static class BuilderWithParent implements OFMatchV1.Builder {
+        final OFMatchV1Ver10 parentMessage;
+
+        // OF message fields
+        private boolean wildcardsSet;
+        private int wildcards;
+        private boolean inPortSet;
+        private OFPort inPort;
+        private boolean ethSrcSet;
+        private MacAddress ethSrc;
+        private boolean ethDstSet;
+        private MacAddress ethDst;
+        private boolean vlanVidSet;
+        private OFVlanVidMatch vlanVid;
+        private boolean vlanPcpSet;
+        private VlanPcp vlanPcp;
+        private boolean ethTypeSet;
+        private EthType ethType;
+        private boolean ipDscpSet;
+        private IpDscp ipDscp;
+        private boolean ipProtoSet;
+        private IpProtocol ipProto;
+        private boolean ipv4SrcSet;
+        private IPv4Address ipv4Src;
+        private boolean ipv4DstSet;
+        private IPv4Address ipv4Dst;
+        private boolean tcpSrcSet;
+        private TransportPort tcpSrc;
+        private boolean tcpDstSet;
+        private TransportPort tcpDst;
+
+        BuilderWithParent(OFMatchV1Ver10 parentMessage) {
+            this.parentMessage = parentMessage;
+        }
+
+    @Override
+    public int getWildcards() {
+        return wildcards;
+    }
+
+    @Override
+    public OFMatchV1.Builder setWildcards(int wildcards) {
+        this.wildcards = wildcards;
+        this.wildcardsSet = true;
+        return this;
+    }
+    @Override
+    public OFPort getInPort() {
+        return inPort;
+    }
+
+    @Override
+    public OFMatchV1.Builder setInPort(OFPort inPort) {
+        this.inPort = inPort;
+        this.inPortSet = true;
+        return this;
+    }
+    @Override
+    public MacAddress getEthSrc() {
+        return ethSrc;
+    }
+
+    @Override
+    public OFMatchV1.Builder setEthSrc(MacAddress ethSrc) {
+        this.ethSrc = ethSrc;
+        this.ethSrcSet = true;
+        return this;
+    }
+    @Override
+    public MacAddress getEthDst() {
+        return ethDst;
+    }
+
+    @Override
+    public OFMatchV1.Builder setEthDst(MacAddress ethDst) {
+        this.ethDst = ethDst;
+        this.ethDstSet = true;
+        return this;
+    }
+    @Override
+    public OFVlanVidMatch getVlanVid() {
+        return vlanVid;
+    }
+
+    @Override
+    public OFMatchV1.Builder setVlanVid(OFVlanVidMatch vlanVid) {
+        this.vlanVid = vlanVid;
+        this.vlanVidSet = true;
+        return this;
+    }
+    @Override
+    public VlanPcp getVlanPcp() {
+        return vlanPcp;
+    }
+
+    @Override
+    public OFMatchV1.Builder setVlanPcp(VlanPcp vlanPcp) {
+        this.vlanPcp = vlanPcp;
+        this.vlanPcpSet = true;
+        return this;
+    }
+    @Override
+    public EthType getEthType() {
+        return ethType;
+    }
+
+    @Override
+    public OFMatchV1.Builder setEthType(EthType ethType) {
+        this.ethType = ethType;
+        this.ethTypeSet = true;
+        return this;
+    }
+    @Override
+    public IpDscp getIpDscp() {
+        return ipDscp;
+    }
+
+    @Override
+    public OFMatchV1.Builder setIpDscp(IpDscp ipDscp) {
+        this.ipDscp = ipDscp;
+        this.ipDscpSet = true;
+        return this;
+    }
+    @Override
+    public IpProtocol getIpProto() {
+        return ipProto;
+    }
+
+    @Override
+    public OFMatchV1.Builder setIpProto(IpProtocol ipProto) {
+        this.ipProto = ipProto;
+        this.ipProtoSet = true;
+        return this;
+    }
+    @Override
+    public IPv4Address getIpv4Src() {
+        return ipv4Src;
+    }
+
+    @Override
+    public OFMatchV1.Builder setIpv4Src(IPv4Address ipv4Src) {
+        this.ipv4Src = ipv4Src;
+        this.ipv4SrcSet = true;
+        return this;
+    }
+    @Override
+    public IPv4Address getIpv4Dst() {
+        return ipv4Dst;
+    }
+
+    @Override
+    public OFMatchV1.Builder setIpv4Dst(IPv4Address ipv4Dst) {
+        this.ipv4Dst = ipv4Dst;
+        this.ipv4DstSet = true;
+        return this;
+    }
+    @Override
+    public TransportPort getTcpSrc() {
+        return tcpSrc;
+    }
+
+    @Override
+    public OFMatchV1.Builder setTcpSrc(TransportPort tcpSrc) {
+        this.tcpSrc = tcpSrc;
+        this.tcpSrcSet = true;
+        return this;
+    }
+    @Override
+    public TransportPort getTcpDst() {
+        return tcpDst;
+    }
+
+    @Override
+    public OFMatchV1.Builder setTcpDst(TransportPort tcpDst) {
+        this.tcpDst = tcpDst;
+        this.tcpDstSet = true;
+        return this;
+    }
+    @Override
+    public OFVersion getVersion() {
+        return OFVersion.OF_10;
+    }
+
+
+
+        @Override
+        public OFMatchV1 build() {
+                int wildcards = this.wildcardsSet ? this.wildcards : parentMessage.wildcards;
+                OFPort inPort = this.inPortSet ? this.inPort : parentMessage.inPort;
+                if(inPort == null)
+                    throw new NullPointerException("Property inPort must not be null");
+                MacAddress ethSrc = this.ethSrcSet ? this.ethSrc : parentMessage.ethSrc;
+                if(ethSrc == null)
+                    throw new NullPointerException("Property ethSrc must not be null");
+                MacAddress ethDst = this.ethDstSet ? this.ethDst : parentMessage.ethDst;
+                if(ethDst == null)
+                    throw new NullPointerException("Property ethDst must not be null");
+                OFVlanVidMatch vlanVid = this.vlanVidSet ? this.vlanVid : parentMessage.vlanVid;
+                if(vlanVid == null)
+                    throw new NullPointerException("Property vlanVid must not be null");
+                VlanPcp vlanPcp = this.vlanPcpSet ? this.vlanPcp : parentMessage.vlanPcp;
+                if(vlanPcp == null)
+                    throw new NullPointerException("Property vlanPcp must not be null");
+                EthType ethType = this.ethTypeSet ? this.ethType : parentMessage.ethType;
+                if(ethType == null)
+                    throw new NullPointerException("Property ethType must not be null");
+                IpDscp ipDscp = this.ipDscpSet ? this.ipDscp : parentMessage.ipDscp;
+                if(ipDscp == null)
+                    throw new NullPointerException("Property ipDscp must not be null");
+                IpProtocol ipProto = this.ipProtoSet ? this.ipProto : parentMessage.ipProto;
+                if(ipProto == null)
+                    throw new NullPointerException("Property ipProto must not be null");
+                IPv4Address ipv4Src = this.ipv4SrcSet ? this.ipv4Src : parentMessage.ipv4Src;
+                if(ipv4Src == null)
+                    throw new NullPointerException("Property ipv4Src must not be null");
+                IPv4Address ipv4Dst = this.ipv4DstSet ? this.ipv4Dst : parentMessage.ipv4Dst;
+                if(ipv4Dst == null)
+                    throw new NullPointerException("Property ipv4Dst must not be null");
+                TransportPort tcpSrc = this.tcpSrcSet ? this.tcpSrc : parentMessage.tcpSrc;
+                if(tcpSrc == null)
+                    throw new NullPointerException("Property tcpSrc must not be null");
+                TransportPort tcpDst = this.tcpDstSet ? this.tcpDst : parentMessage.tcpDst;
+                if(tcpDst == null)
+                    throw new NullPointerException("Property tcpDst must not be null");
+
+                //
+            // normalize match fields according to current OpenVSwitch behavior. When prerequisites for a field are not met
+            // e.g., eth_type is not set to 0x800, OVS sets the value of corresponding ignored fields (e.g.,
+            // ip_src, tcp_dst) to 0, and sets the wildcard bit to 1.
+            if(ethType.equals(EthType.IPv4)) {
+                // IP
+                if(ipProto.equals(IpProtocol.TCP) || ipProto.equals(IpProtocol.UDP) || ipProto.equals(IpProtocol.ICMP)) {
+                    // fully speced, wildcards and all values are fine
+                    // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                        wildcards |= OFPFW_NW_SRC_MASK;
+
+                    // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                        wildcards |= OFPFW_NW_DST_MASK;
+
+                } else {
+                    // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                        wildcards |= OFPFW_NW_SRC_MASK;
+
+                    // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                        wildcards |= OFPFW_NW_DST_MASK;
+
+                    // not TCP/UDP/ICMP -> Clear TP wildcards for the wire
+                    wildcards |= (OFPFW_TP_SRC | OFPFW_TP_DST);
+                    tcpSrc = TransportPort.NONE;
+                    tcpDst = TransportPort.NONE;
+                }
+            } else if (ethType.equals(EthType.ARP)) {
+                // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                    wildcards |= OFPFW_NW_SRC_MASK;
+
+                // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                    wildcards |= OFPFW_NW_DST_MASK;
+
+                // ARP: clear NW_TOS / TP wildcards for the wire
+                wildcards |= ( OFPFW_NW_TOS | OFPFW_TP_SRC | OFPFW_TP_DST);
+                ipDscp = IpDscp.NONE;
+                tcpSrc = TransportPort.NONE;
+                tcpDst = TransportPort.NONE;
+            } else {
+                // not even IP. Clear NW/TP wildcards for the wire
+                wildcards |= ( OFPFW_NW_TOS | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_TP_SRC | OFPFW_TP_DST);
+                ipDscp = IpDscp.NONE;
+                ipProto = IpProtocol.NONE;
+                ipv4Src = IPv4Address.NONE;
+                ipv4Dst = IPv4Address.NONE;
+                tcpSrc = TransportPort.NONE;
+                tcpDst = TransportPort.NONE;
+            }
+                return new OFMatchV1Ver10(
+                    wildcards,
+                    inPort,
+                    ethSrc,
+                    ethDst,
+                    vlanVid,
+                    vlanPcp,
+                    ethType,
+                    ipDscp,
+                    ipProto,
+                    ipv4Src,
+                    ipv4Dst,
+                    tcpSrc,
+                    tcpDst
+                );
+        }
+        @SuppressWarnings("unchecked")
+        @Override
+        public <F extends OFValueType<F>> F get(MatchField<F> field)
+                throws UnsupportedOperationException {
+            if (isFullyWildcarded(field))
+                return null;
+
+            Object result;
+            switch (field.id) {
+                case IN_PORT:
+                    result = inPort;
+                    break;
+                case ETH_DST:
+                    result = ethDst;
+                    break;
+                case ETH_SRC:
+                    result = ethSrc;
+                    break;
+                case ETH_TYPE:
+                    result = ethType;
+                    break;
+                case VLAN_VID:
+                    result = vlanVid;
+                    break;
+                case VLAN_PCP:
+                    result = vlanPcp;
+                    break;
+                case ARP_OP:
+                    result = ArpOpcode.of(ipProto.getIpProtocolNumber());
+                    break;
+                case ARP_SPA:
+                    result = ipv4Src;
+                    break;
+                case ARP_TPA:
+                    result = ipv4Dst;
+                    break;
+                case IP_DSCP:
+                    result = ipDscp;
+                    break;
+                case IP_PROTO:
+                    result = ipProto;
+                    break;
+                case IPV4_SRC:
+                    result = ipv4Src;
+                    break;
+                case IPV4_DST:
+                    result = ipv4Dst;
+                    break;
+                case TCP_SRC:
+                    result = tcpSrc;
+                    break;
+                case TCP_DST:
+                    result = tcpDst;
+                    break;
+                case UDP_SRC:
+                    result = tcpSrc;
+                    break;
+                case UDP_DST:
+                    result = tcpDst;
+                    break;
+                case SCTP_SRC:
+                    result = tcpSrc;
+                    break;
+                case SCTP_DST:
+                    result = tcpDst;
+                    break;
+                case ICMPV4_TYPE:
+                    result = tcpSrc;
+                    break;
+                case ICMPV4_CODE:
+                    result = tcpDst;
+                    break;
+                // NOT SUPPORTED:
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+            }
+            return (F)result;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+                throws UnsupportedOperationException {
+            if (!isPartiallyMasked(field))
+                return null;
+            Object result;
+            switch (field.id) {
+                case IPV4_SRC:
+                case ARP_SPA:
+                    int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
+                    result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
+                    break;
+                case IPV4_DST:
+                case ARP_TPA:
+                    int dstMaskedBits = Math.min(32, (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT);
+                    int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
+
+                    result = IPv4AddressWithMask.of(ipv4Dst, IPv4Address.of(dstBitMask));
+                    break;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+            }
+            return (Masked<F>)result;
+        }
+
+        @Override
+        public boolean supports(MatchField<?> field) {
+            switch (field.id) {
+                case IN_PORT:
+                case ETH_DST:
+                case ETH_SRC:
+                case ETH_TYPE:
+                case VLAN_VID:
+                case VLAN_PCP:
+                case ARP_OP:
+                case ARP_SPA:
+                case ARP_TPA:
+                case IP_DSCP:
+                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:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        @Override
+        public boolean supportsMasked(MatchField<?> field) {
+            switch (field.id) {
+                case ARP_SPA:
+                case ARP_TPA:
+                case IPV4_SRC:
+                case IPV4_DST:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        @Override
+        public boolean isExact(MatchField<?> field) {
+            switch (field.id) {
+                case IN_PORT:
+                    return (this.wildcards & OFPFW_IN_PORT) == 0;
+                case ETH_DST:
+                    return (this.wildcards & OFPFW_DL_DST) == 0;
+                case ETH_SRC:
+                    return (this.wildcards & OFPFW_DL_SRC) == 0;
+                case ETH_TYPE:
+                    return (this.wildcards & OFPFW_DL_TYPE) == 0;
+                case VLAN_VID:
+                    return (this.wildcards & OFPFW_DL_VLAN) == 0;
+                case VLAN_PCP:
+                    return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
+                case ARP_OP:
+                    return (this.wildcards & OFPFW_NW_PROTO) == 0;
+                case ARP_SPA:
+                    return this.getIpv4SrcCidrMaskLen() >= 32;
+                case ARP_TPA:
+                    return this.getIpv4DstCidrMaskLen() >= 32;
+                case IP_DSCP:
+                    return (this.wildcards & OFPFW_NW_TOS) == 0;
+                case IP_PROTO:
+                    return (this.wildcards & OFPFW_NW_PROTO) == 0;
+                case IPV4_SRC:
+                    return this.getIpv4SrcCidrMaskLen() >= 32;
+                case IPV4_DST:
+                    return this.getIpv4DstCidrMaskLen() >= 32;
+                case TCP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) == 0;
+                case TCP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) == 0;
+                case UDP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) == 0;
+                case UDP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) == 0;
+                case SCTP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) == 0;
+                case SCTP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) == 0;
+                case ICMPV4_TYPE:
+                    return (this.wildcards & OFPFW_TP_SRC) == 0;
+                case ICMPV4_CODE:
+                    return (this.wildcards & OFPFW_TP_DST) == 0;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+            }
+        }
+
+        /**
+         * Parse this match's wildcard fields and return the number of significant
+         * bits in the IP destination field. NOTE: this returns the number of bits
+         * that are fixed, i.e., like CIDR, not the number of bits that are free
+         * like OpenFlow encodes.
+         *
+         * @return A number between 0 (matches all IPs) and 32 (exact match)
+         */
+        public int getIpv4DstCidrMaskLen() {
+            return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
+                            0);
+        }
+
+        /**
+         * Parse this match's wildcard fields and return the number of significant
+         * bits in the IP destination field. NOTE: this returns the number of bits
+         * that are fixed, i.e., like CIDR, not the number of bits that are free
+         * like OpenFlow encodes.
+         *
+         * @return A number between 0 (matches all IPs) and 32 (exact match)
+         */
+        public int getIpv4SrcCidrMaskLen() {
+            return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
+                            0);
+        }
+
+
+        @Override
+        public boolean isFullyWildcarded(MatchField<?> field) {
+            switch (field.id) {
+                case IN_PORT:
+                    return (this.wildcards & OFPFW_IN_PORT) != 0;
+                case ETH_DST:
+                    return (this.wildcards & OFPFW_DL_DST) != 0;
+                case ETH_SRC:
+                    return (this.wildcards & OFPFW_DL_SRC) != 0;
+                case ETH_TYPE:
+                    return (this.wildcards & OFPFW_DL_TYPE) != 0;
+                case VLAN_VID:
+                    return (this.wildcards & OFPFW_DL_VLAN) != 0;
+                case VLAN_PCP:
+                    return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
+                case ARP_OP:
+                    return (this.wildcards & OFPFW_NW_PROTO) != 0;
+                case ARP_SPA:
+                    return this.getIpv4SrcCidrMaskLen() <= 0;
+                case ARP_TPA:
+                    return this.getIpv4DstCidrMaskLen() <= 0;
+                case IP_DSCP:
+                    return (this.wildcards & OFPFW_NW_TOS) != 0;
+                case IP_PROTO:
+                    return (this.wildcards & OFPFW_NW_PROTO) != 0;
+                case TCP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) != 0;
+                case TCP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) != 0;
+                case UDP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) != 0;
+                case UDP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) != 0;
+                case SCTP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) != 0;
+                case SCTP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) != 0;
+                case ICMPV4_TYPE:
+                    return (this.wildcards & OFPFW_TP_SRC) != 0;
+                case ICMPV4_CODE:
+                    return (this.wildcards & OFPFW_TP_DST) != 0;
+                case IPV4_SRC:
+                    return this.getIpv4SrcCidrMaskLen() <= 0;
+                case IPV4_DST:
+                    return this.getIpv4DstCidrMaskLen() <= 0;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+            }
+        }
+
+        @Override
+        public boolean isPartiallyMasked(MatchField<?> field) {
+            switch (field.id) {
+                case ARP_SPA:
+                case IPV4_SRC:
+                    int srcCidrLen = getIpv4SrcCidrMaskLen();
+                    return srcCidrLen > 0 && srcCidrLen < 32;
+                case ARP_TPA:
+                case IPV4_DST:
+                    int dstCidrLen = getIpv4DstCidrMaskLen();
+                    return dstCidrLen > 0 && dstCidrLen < 32;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+            }
+        }
+
+        private final void initWildcards() {
+            if(!wildcardsSet) {
+                wildcards = parentMessage.wildcards;
+                wildcardsSet = true;
+            }
+        }
+
+        @Override
+        public <F extends OFValueType<F>> Match.Builder setExact(MatchField<F> field,
+                F value) {
+            initWildcards();
+            Object val = value;
+            switch (field.id) {
+                case ETH_DST:
+                    setEthDst((MacAddress) value);
+                    wildcards &= ~OFPFW_DL_DST;
+                    break;
+                case ETH_SRC:
+                    setEthSrc((MacAddress) value);
+                    wildcards &= ~OFPFW_DL_SRC;
+                    break;
+                case ETH_TYPE:
+                    setEthType((EthType) value);
+                    wildcards &= ~OFPFW_DL_TYPE;
+                    break;
+                case ICMPV4_CODE:
+                    setTcpDst(TransportPort.of(((ICMPv4Code)value).getCode()));
+                    wildcards &= ~OFPFW_TP_DST;
+                    break;
+                case ICMPV4_TYPE:
+                    setTcpSrc(TransportPort.of(((ICMPv4Type)value).getType()));
+                    wildcards &= ~OFPFW_TP_SRC;
+                    break;
+                case IN_PORT:
+                    setInPort((OFPort) value);
+                    wildcards &= ~OFPFW_IN_PORT;
+                    break;
+                case ARP_OP:
+                    setIpProto(IpProtocol.of((short)((ArpOpcode)value).getOpcode()));
+                    wildcards &= ~OFPFW_NW_PROTO;
+                    break;
+                case ARP_TPA:
+                case IPV4_DST:
+                    setIpv4Dst((IPv4Address) value);
+                    wildcards &= ~OFPFW_NW_DST_MASK;
+                    break;
+                case ARP_SPA:
+                case IPV4_SRC:
+                    setIpv4Src((IPv4Address) value);
+                    wildcards &= ~OFPFW_NW_SRC_MASK;
+                    break;
+                case IP_DSCP:
+                    setIpDscp((IpDscp) value);
+                    wildcards &= ~OFPFW_NW_TOS;
+                    break;
+                case IP_PROTO:
+                    setIpProto((IpProtocol) value);
+                    wildcards &= ~OFPFW_NW_PROTO;
+                    break;
+                case SCTP_DST:
+                    setTcpDst((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_DST;
+                    break;
+                case SCTP_SRC:
+                    setTcpSrc((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_SRC;
+                    break;
+                case TCP_DST:
+                    setTcpDst((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_DST;
+                    break;
+                case TCP_SRC:
+                    setTcpSrc((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_SRC;
+                    break;
+                case UDP_DST:
+                    setTcpDst((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_DST;
+                    break;
+                case UDP_SRC:
+                    setTcpSrc((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_SRC;
+                    break;
+                case VLAN_PCP:
+                    setVlanPcp((VlanPcp) value);
+                    wildcards &= ~OFPFW_DL_VLAN_PCP;
+                    break;
+                case VLAN_VID:
+                    setVlanVid((OFVlanVidMatch) value);
+                    wildcards &= ~OFPFW_DL_VLAN;
+                    break;
+                default:
+                    throw new UnsupportedOperationException(
+                            "OFMatch does not support matching on field " + field.getName());
+            }
+            return this;
+        }
+
+        @Override
+        public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field,
+                F value, F mask) {
+            initWildcards();
+            switch (field.id) {
+                case ARP_SPA:
+                case ARP_TPA:
+                case IPV4_DST:
+                case IPV4_SRC:
+                    Object valObj = value;
+                    Object masObj = mask;
+                    IPv4Address ip = ((IPv4Address)valObj);
+                    int maskval = ((IPv4Address)masObj).getInt();
+                    if (Integer.bitCount(~maskval + 1) != 1)
+                        throw new UnsupportedOperationException("OFMatch only supports CIDR masks for IPv4");
+                    int maskLen = 32 - Integer.bitCount(maskval);
+                    switch(field.id) {
+                        case ARP_TPA:
+                        case IPV4_DST:
+                            setIpv4Dst(ip);
+                            wildcards = (wildcards &~OFPFW_NW_DST_MASK) | (maskLen << OFPFW_NW_DST_SHIFT);
+                            break;
+                        case ARP_SPA:
+                        case IPV4_SRC:
+                            setIpv4Src(ip);
+                            wildcards = (wildcards &~OFPFW_NW_SRC_MASK) | (maskLen << OFPFW_NW_SRC_SHIFT);
+                            break;
+                        default:
+                            // Cannot really get here
+                            break;
+                    }
+                    break;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+            }
+            return this;
+        }
+
+        @Override
+        public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field, Masked<F> valueWithMask)
+                                                                       throws UnsupportedOperationException {
+            return this.setMasked(field, valueWithMask.getValue(), valueWithMask.getMask());
+        }
+
+        @Override
+        public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+            initWildcards();
+            switch (field.id) {
+                case ETH_DST:
+                    setEthDst(MacAddress.NONE);
+                    wildcards |= OFPFW_DL_DST;
+                    break;
+                case ETH_SRC:
+                    setEthSrc(MacAddress.NONE);
+                    wildcards |= OFPFW_DL_SRC;
+                    break;
+                case ETH_TYPE:
+                    setEthType(EthType.NONE);
+                    wildcards |= OFPFW_DL_TYPE;
+                    break;
+                case ICMPV4_CODE:
+                case TCP_DST:
+                case UDP_DST:
+                case SCTP_DST:
+                    setTcpDst(TransportPort.NONE);
+                    wildcards |= OFPFW_TP_DST;
+                    break;
+                case ICMPV4_TYPE:
+                case TCP_SRC:
+                case UDP_SRC:
+                case SCTP_SRC:
+                    setTcpSrc(TransportPort.NONE);
+                    wildcards |= OFPFW_TP_SRC;
+                    break;
+                case IN_PORT:
+                    setInPort(OFPort.of(0)); // NOTE: not 'NONE' -- that is 0xFF for ports
+                    wildcards |= OFPFW_IN_PORT;
+                    break;
+                case ARP_TPA:
+                case IPV4_DST:
+                    setIpv4Dst(IPv4Address.NONE);
+                    wildcards |= OFPFW_NW_DST_MASK;
+                    break;
+                case ARP_SPA:
+                case IPV4_SRC:
+                    setIpv4Src(IPv4Address.NONE);
+                    wildcards |= OFPFW_NW_SRC_MASK;
+                    break;
+                case IP_DSCP:
+                    setIpDscp(IpDscp.NONE);
+                    wildcards |= OFPFW_NW_TOS;
+                    break;
+                case IP_PROTO:
+                    setIpProto(IpProtocol.NONE);
+                    wildcards |= OFPFW_NW_PROTO;
+                    break;
+                case VLAN_PCP:
+                    setVlanPcp(VlanPcp.NONE);
+                    wildcards |= OFPFW_DL_VLAN_PCP;
+                    break;
+                case VLAN_VID:
+                    setVlanVid(OFVlanVidMatch.NONE);
+                    wildcards |= OFPFW_DL_VLAN;
+                    break;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+            }
+            return this;
+        }
+
+    }
+
+    static class Builder implements OFMatchV1.Builder {
+        // OF message fields
+        private boolean wildcardsSet;
+        private int wildcards;
+        private boolean inPortSet;
+        private OFPort inPort;
+        private boolean ethSrcSet;
+        private MacAddress ethSrc;
+        private boolean ethDstSet;
+        private MacAddress ethDst;
+        private boolean vlanVidSet;
+        private OFVlanVidMatch vlanVid;
+        private boolean vlanPcpSet;
+        private VlanPcp vlanPcp;
+        private boolean ethTypeSet;
+        private EthType ethType;
+        private boolean ipDscpSet;
+        private IpDscp ipDscp;
+        private boolean ipProtoSet;
+        private IpProtocol ipProto;
+        private boolean ipv4SrcSet;
+        private IPv4Address ipv4Src;
+        private boolean ipv4DstSet;
+        private IPv4Address ipv4Dst;
+        private boolean tcpSrcSet;
+        private TransportPort tcpSrc;
+        private boolean tcpDstSet;
+        private TransportPort tcpDst;
+
+    @Override
+    public int getWildcards() {
+        return wildcards;
+    }
+
+    @Override
+    public OFMatchV1.Builder setWildcards(int wildcards) {
+        this.wildcards = wildcards;
+        this.wildcardsSet = true;
+        return this;
+    }
+    @Override
+    public OFPort getInPort() {
+        return inPort;
+    }
+
+    @Override
+    public OFMatchV1.Builder setInPort(OFPort inPort) {
+        this.inPort = inPort;
+        this.inPortSet = true;
+        return this;
+    }
+    @Override
+    public MacAddress getEthSrc() {
+        return ethSrc;
+    }
+
+    @Override
+    public OFMatchV1.Builder setEthSrc(MacAddress ethSrc) {
+        this.ethSrc = ethSrc;
+        this.ethSrcSet = true;
+        return this;
+    }
+    @Override
+    public MacAddress getEthDst() {
+        return ethDst;
+    }
+
+    @Override
+    public OFMatchV1.Builder setEthDst(MacAddress ethDst) {
+        this.ethDst = ethDst;
+        this.ethDstSet = true;
+        return this;
+    }
+    @Override
+    public OFVlanVidMatch getVlanVid() {
+        return vlanVid;
+    }
+
+    @Override
+    public OFMatchV1.Builder setVlanVid(OFVlanVidMatch vlanVid) {
+        this.vlanVid = vlanVid;
+        this.vlanVidSet = true;
+        return this;
+    }
+    @Override
+    public VlanPcp getVlanPcp() {
+        return vlanPcp;
+    }
+
+    @Override
+    public OFMatchV1.Builder setVlanPcp(VlanPcp vlanPcp) {
+        this.vlanPcp = vlanPcp;
+        this.vlanPcpSet = true;
+        return this;
+    }
+    @Override
+    public EthType getEthType() {
+        return ethType;
+    }
+
+    @Override
+    public OFMatchV1.Builder setEthType(EthType ethType) {
+        this.ethType = ethType;
+        this.ethTypeSet = true;
+        return this;
+    }
+    @Override
+    public IpDscp getIpDscp() {
+        return ipDscp;
+    }
+
+    @Override
+    public OFMatchV1.Builder setIpDscp(IpDscp ipDscp) {
+        this.ipDscp = ipDscp;
+        this.ipDscpSet = true;
+        return this;
+    }
+    @Override
+    public IpProtocol getIpProto() {
+        return ipProto;
+    }
+
+    @Override
+    public OFMatchV1.Builder setIpProto(IpProtocol ipProto) {
+        this.ipProto = ipProto;
+        this.ipProtoSet = true;
+        return this;
+    }
+    @Override
+    public IPv4Address getIpv4Src() {
+        return ipv4Src;
+    }
+
+    @Override
+    public OFMatchV1.Builder setIpv4Src(IPv4Address ipv4Src) {
+        this.ipv4Src = ipv4Src;
+        this.ipv4SrcSet = true;
+        return this;
+    }
+    @Override
+    public IPv4Address getIpv4Dst() {
+        return ipv4Dst;
+    }
+
+    @Override
+    public OFMatchV1.Builder setIpv4Dst(IPv4Address ipv4Dst) {
+        this.ipv4Dst = ipv4Dst;
+        this.ipv4DstSet = true;
+        return this;
+    }
+    @Override
+    public TransportPort getTcpSrc() {
+        return tcpSrc;
+    }
+
+    @Override
+    public OFMatchV1.Builder setTcpSrc(TransportPort tcpSrc) {
+        this.tcpSrc = tcpSrc;
+        this.tcpSrcSet = true;
+        return this;
+    }
+    @Override
+    public TransportPort getTcpDst() {
+        return tcpDst;
+    }
+
+    @Override
+    public OFMatchV1.Builder setTcpDst(TransportPort tcpDst) {
+        this.tcpDst = tcpDst;
+        this.tcpDstSet = true;
+        return this;
+    }
+    @Override
+    public OFVersion getVersion() {
+        return OFVersion.OF_10;
+    }
+
+//
+        @Override
+        public OFMatchV1 build() {
+            int wildcards = this.wildcardsSet ? this.wildcards : DEFAULT_WILDCARDS;
+            OFPort inPort = this.inPortSet ? this.inPort : DEFAULT_IN_PORT;
+            if(inPort == null)
+                throw new NullPointerException("Property inPort must not be null");
+            MacAddress ethSrc = this.ethSrcSet ? this.ethSrc : DEFAULT_ETH_SRC;
+            if(ethSrc == null)
+                throw new NullPointerException("Property ethSrc must not be null");
+            MacAddress ethDst = this.ethDstSet ? this.ethDst : DEFAULT_ETH_DST;
+            if(ethDst == null)
+                throw new NullPointerException("Property ethDst must not be null");
+            OFVlanVidMatch vlanVid = this.vlanVidSet ? this.vlanVid : DEFAULT_VLAN_VID;
+            if(vlanVid == null)
+                throw new NullPointerException("Property vlanVid must not be null");
+            VlanPcp vlanPcp = this.vlanPcpSet ? this.vlanPcp : DEFAULT_VLAN_PCP;
+            if(vlanPcp == null)
+                throw new NullPointerException("Property vlanPcp must not be null");
+            EthType ethType = this.ethTypeSet ? this.ethType : DEFAULT_ETH_TYPE;
+            if(ethType == null)
+                throw new NullPointerException("Property ethType must not be null");
+            IpDscp ipDscp = this.ipDscpSet ? this.ipDscp : DEFAULT_IP_DSCP;
+            if(ipDscp == null)
+                throw new NullPointerException("Property ipDscp must not be null");
+            IpProtocol ipProto = this.ipProtoSet ? this.ipProto : DEFAULT_IP_PROTO;
+            if(ipProto == null)
+                throw new NullPointerException("Property ipProto must not be null");
+            IPv4Address ipv4Src = this.ipv4SrcSet ? this.ipv4Src : DEFAULT_IPV4_SRC;
+            if(ipv4Src == null)
+                throw new NullPointerException("Property ipv4Src must not be null");
+            IPv4Address ipv4Dst = this.ipv4DstSet ? this.ipv4Dst : DEFAULT_IPV4_DST;
+            if(ipv4Dst == null)
+                throw new NullPointerException("Property ipv4Dst must not be null");
+            TransportPort tcpSrc = this.tcpSrcSet ? this.tcpSrc : DEFAULT_TCP_SRC;
+            if(tcpSrc == null)
+                throw new NullPointerException("Property tcpSrc must not be null");
+            TransportPort tcpDst = this.tcpDstSet ? this.tcpDst : DEFAULT_TCP_DST;
+            if(tcpDst == null)
+                throw new NullPointerException("Property tcpDst must not be null");
+
+            // normalize match fields according to current OpenVSwitch behavior. When prerequisites for a field are not met
+            // e.g., eth_type is not set to 0x800, OVS sets the value of corresponding ignored fields (e.g.,
+            // ip_src, tcp_dst) to 0, and sets the wildcard bit to 1.
+            if(ethType.equals(EthType.IPv4)) {
+                // IP
+                if(ipProto.equals(IpProtocol.TCP) || ipProto.equals(IpProtocol.UDP) || ipProto.equals(IpProtocol.ICMP)) {
+                    // fully speced, wildcards and all values are fine
+                    // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                        wildcards |= OFPFW_NW_SRC_MASK;
+
+                    // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                        wildcards |= OFPFW_NW_DST_MASK;
+
+                } else {
+                    // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                        wildcards |= OFPFW_NW_SRC_MASK;
+
+                    // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                        wildcards |= OFPFW_NW_DST_MASK;
+
+                    // not TCP/UDP/ICMP -> Clear TP wildcards for the wire
+                    wildcards |= (OFPFW_TP_SRC | OFPFW_TP_DST);
+                    tcpSrc = TransportPort.NONE;
+                    tcpDst = TransportPort.NONE;
+                }
+            } else if (ethType.equals(EthType.ARP)) {
+                // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                    wildcards |= OFPFW_NW_SRC_MASK;
+
+                // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                    wildcards |= OFPFW_NW_DST_MASK;
+
+                // ARP: clear NW_TOS / TP wildcards for the wire
+                wildcards |= ( OFPFW_NW_TOS | OFPFW_TP_SRC | OFPFW_TP_DST);
+                ipDscp = IpDscp.NONE;
+                tcpSrc = TransportPort.NONE;
+                tcpDst = TransportPort.NONE;
+            } else {
+                // not even IP. Clear NW/TP wildcards for the wire
+                wildcards |= ( OFPFW_NW_TOS | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_TP_SRC | OFPFW_TP_DST);
+                ipDscp = IpDscp.NONE;
+                ipProto = IpProtocol.NONE;
+                ipv4Src = IPv4Address.NONE;
+                ipv4Dst = IPv4Address.NONE;
+                tcpSrc = TransportPort.NONE;
+                tcpDst = TransportPort.NONE;
+            }
+
+            return new OFMatchV1Ver10(
+                    wildcards,
+                    inPort,
+                    ethSrc,
+                    ethDst,
+                    vlanVid,
+                    vlanPcp,
+                    ethType,
+                    ipDscp,
+                    ipProto,
+                    ipv4Src,
+                    ipv4Dst,
+                    tcpSrc,
+                    tcpDst
+                );
+        }
+        @SuppressWarnings("unchecked")
+        @Override
+        public <F extends OFValueType<F>> F get(MatchField<F> field)
+                throws UnsupportedOperationException {
+            if (isFullyWildcarded(field))
+                return null;
+
+            Object result;
+            switch (field.id) {
+                case IN_PORT:
+                    result = inPort;
+                    break;
+                case ETH_DST:
+                    result = ethDst;
+                    break;
+                case ETH_SRC:
+                    result = ethSrc;
+                    break;
+                case ETH_TYPE:
+                    result = ethType;
+                    break;
+                case VLAN_VID:
+                    result = vlanVid;
+                    break;
+                case VLAN_PCP:
+                    result = vlanPcp;
+                    break;
+                case ARP_OP:
+                    result = ArpOpcode.of(ipProto.getIpProtocolNumber());
+                    break;
+                case ARP_SPA:
+                    result = ipv4Src;
+                    break;
+                case ARP_TPA:
+                    result = ipv4Dst;
+                    break;
+                case IP_DSCP:
+                    result = ipDscp;
+                    break;
+                case IP_PROTO:
+                    result = ipProto;
+                    break;
+                case IPV4_SRC:
+                    result = ipv4Src;
+                    break;
+                case IPV4_DST:
+                    result = ipv4Dst;
+                    break;
+                case TCP_SRC:
+                    result = tcpSrc;
+                    break;
+                case TCP_DST:
+                    result = tcpDst;
+                    break;
+                case UDP_SRC:
+                    result = tcpSrc;
+                    break;
+                case UDP_DST:
+                    result = tcpDst;
+                    break;
+                case SCTP_SRC:
+                    result = tcpSrc;
+                    break;
+                case SCTP_DST:
+                    result = tcpDst;
+                    break;
+                case ICMPV4_TYPE:
+                    result = tcpSrc;
+                    break;
+                case ICMPV4_CODE:
+                    result = tcpDst;
+                    break;
+                // NOT SUPPORTED:
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+            }
+            return (F)result;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+                throws UnsupportedOperationException {
+            if (!isPartiallyMasked(field))
+                return null;
+            Object result;
+            switch (field.id) {
+                case IPV4_SRC:
+                case ARP_SPA:
+                    int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
+                    result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
+                    break;
+                case IPV4_DST:
+                case ARP_TPA:
+                    int dstMaskedBits = Math.min(32, (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT);
+                    int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
+
+                    result = IPv4AddressWithMask.of(ipv4Dst, IPv4Address.of(dstBitMask));
+                    break;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+            }
+            return (Masked<F>)result;
+        }
+
+        @Override
+        public boolean supports(MatchField<?> field) {
+            switch (field.id) {
+                case IN_PORT:
+                case ETH_DST:
+                case ETH_SRC:
+                case ETH_TYPE:
+                case VLAN_VID:
+                case VLAN_PCP:
+                case ARP_OP:
+                case ARP_SPA:
+                case ARP_TPA:
+                case IP_DSCP:
+                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:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        @Override
+        public boolean supportsMasked(MatchField<?> field) {
+            switch (field.id) {
+                case ARP_SPA:
+                case ARP_TPA:
+                case IPV4_SRC:
+                case IPV4_DST:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        @Override
+        public boolean isExact(MatchField<?> field) {
+            switch (field.id) {
+                case IN_PORT:
+                    return (this.wildcards & OFPFW_IN_PORT) == 0;
+                case ETH_DST:
+                    return (this.wildcards & OFPFW_DL_DST) == 0;
+                case ETH_SRC:
+                    return (this.wildcards & OFPFW_DL_SRC) == 0;
+                case ETH_TYPE:
+                    return (this.wildcards & OFPFW_DL_TYPE) == 0;
+                case VLAN_VID:
+                    return (this.wildcards & OFPFW_DL_VLAN) == 0;
+                case VLAN_PCP:
+                    return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
+                case ARP_OP:
+                    return (this.wildcards & OFPFW_NW_PROTO) == 0;
+                case ARP_SPA:
+                    return this.getIpv4SrcCidrMaskLen() >= 32;
+                case ARP_TPA:
+                    return this.getIpv4DstCidrMaskLen() >= 32;
+                case IP_DSCP:
+                    return (this.wildcards & OFPFW_NW_TOS) == 0;
+                case IP_PROTO:
+                    return (this.wildcards & OFPFW_NW_PROTO) == 0;
+                case IPV4_SRC:
+                    return this.getIpv4SrcCidrMaskLen() >= 32;
+                case IPV4_DST:
+                    return this.getIpv4DstCidrMaskLen() >= 32;
+                case TCP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) == 0;
+                case TCP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) == 0;
+                case UDP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) == 0;
+                case UDP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) == 0;
+                case SCTP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) == 0;
+                case SCTP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) == 0;
+                case ICMPV4_TYPE:
+                    return (this.wildcards & OFPFW_TP_SRC) == 0;
+                case ICMPV4_CODE:
+                    return (this.wildcards & OFPFW_TP_DST) == 0;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+            }
+        }
+
+        /**
+         * Parse this match's wildcard fields and return the number of significant
+         * bits in the IP destination field. NOTE: this returns the number of bits
+         * that are fixed, i.e., like CIDR, not the number of bits that are free
+         * like OpenFlow encodes.
+         *
+         * @return A number between 0 (matches all IPs) and 32 (exact match)
+         */
+        public int getIpv4DstCidrMaskLen() {
+            return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
+                            0);
+        }
+
+        /**
+         * Parse this match's wildcard fields and return the number of significant
+         * bits in the IP destination field. NOTE: this returns the number of bits
+         * that are fixed, i.e., like CIDR, not the number of bits that are free
+         * like OpenFlow encodes.
+         *
+         * @return A number between 0 (matches all IPs) and 32 (exact match)
+         */
+        public int getIpv4SrcCidrMaskLen() {
+            return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
+                            0);
+        }
+
+
+        @Override
+        public boolean isFullyWildcarded(MatchField<?> field) {
+            switch (field.id) {
+                case IN_PORT:
+                    return (this.wildcards & OFPFW_IN_PORT) != 0;
+                case ETH_DST:
+                    return (this.wildcards & OFPFW_DL_DST) != 0;
+                case ETH_SRC:
+                    return (this.wildcards & OFPFW_DL_SRC) != 0;
+                case ETH_TYPE:
+                    return (this.wildcards & OFPFW_DL_TYPE) != 0;
+                case VLAN_VID:
+                    return (this.wildcards & OFPFW_DL_VLAN) != 0;
+                case VLAN_PCP:
+                    return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
+                case ARP_OP:
+                    return (this.wildcards & OFPFW_NW_PROTO) != 0;
+                case ARP_SPA:
+                    return this.getIpv4SrcCidrMaskLen() <= 0;
+                case ARP_TPA:
+                    return this.getIpv4DstCidrMaskLen() <= 0;
+                case IP_DSCP:
+                    return (this.wildcards & OFPFW_NW_TOS) != 0;
+                case IP_PROTO:
+                    return (this.wildcards & OFPFW_NW_PROTO) != 0;
+                case TCP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) != 0;
+                case TCP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) != 0;
+                case UDP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) != 0;
+                case UDP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) != 0;
+                case SCTP_SRC:
+                    return (this.wildcards & OFPFW_TP_SRC) != 0;
+                case SCTP_DST:
+                    return (this.wildcards & OFPFW_TP_DST) != 0;
+                case ICMPV4_TYPE:
+                    return (this.wildcards & OFPFW_TP_SRC) != 0;
+                case ICMPV4_CODE:
+                    return (this.wildcards & OFPFW_TP_DST) != 0;
+                case IPV4_SRC:
+                    return this.getIpv4SrcCidrMaskLen() <= 0;
+                case IPV4_DST:
+                    return this.getIpv4DstCidrMaskLen() <= 0;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+            }
+        }
+
+        @Override
+        public boolean isPartiallyMasked(MatchField<?> field) {
+            switch (field.id) {
+                case ARP_SPA:
+                case IPV4_SRC:
+                    int srcCidrLen = getIpv4SrcCidrMaskLen();
+                    return srcCidrLen > 0 && srcCidrLen < 32;
+                case ARP_TPA:
+                case IPV4_DST:
+                    int dstCidrLen = getIpv4DstCidrMaskLen();
+                    return dstCidrLen > 0 && dstCidrLen < 32;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+            }
+        }
+
+        private final void initWildcards() {
+            if(!wildcardsSet) {
+                wildcards = OFPFW_ALL;
+                wildcardsSet = true;
+            }
+        }
+
+        @Override
+        public <F extends OFValueType<F>> Match.Builder setExact(MatchField<F> field,
+                F value) {
+            initWildcards();
+            Object val = value;
+            switch (field.id) {
+                case ETH_DST:
+                    setEthDst((MacAddress) value);
+                    wildcards &= ~OFPFW_DL_DST;
+                    break;
+                case ETH_SRC:
+                    setEthSrc((MacAddress) value);
+                    wildcards &= ~OFPFW_DL_SRC;
+                    break;
+                case ETH_TYPE:
+                    setEthType((EthType) value);
+                    wildcards &= ~OFPFW_DL_TYPE;
+                    break;
+                case ICMPV4_CODE:
+                    setTcpDst(TransportPort.of(((ICMPv4Code)value).getCode()));
+                    wildcards &= ~OFPFW_TP_DST;
+                    break;
+                case ICMPV4_TYPE:
+                    setTcpSrc(TransportPort.of(((ICMPv4Type)value).getType()));
+                    wildcards &= ~OFPFW_TP_SRC;
+                    break;
+                case IN_PORT:
+                    setInPort((OFPort) value);
+                    wildcards &= ~OFPFW_IN_PORT;
+                    break;
+                case ARP_OP:
+                    setIpProto(IpProtocol.of((short)((ArpOpcode)value).getOpcode()));
+                    wildcards &= ~OFPFW_NW_PROTO;
+                    break;
+                case ARP_TPA:
+                case IPV4_DST:
+                    setIpv4Dst((IPv4Address) value);
+                    wildcards &= ~OFPFW_NW_DST_MASK;
+                    break;
+                case ARP_SPA:
+                case IPV4_SRC:
+                    setIpv4Src((IPv4Address) value);
+                    wildcards &= ~OFPFW_NW_SRC_MASK;
+                    break;
+                case IP_DSCP:
+                    setIpDscp((IpDscp) value);
+                    wildcards &= ~OFPFW_NW_TOS;
+                    break;
+                case IP_PROTO:
+                    setIpProto((IpProtocol) value);
+                    wildcards &= ~OFPFW_NW_PROTO;
+                    break;
+                case SCTP_DST:
+                    setTcpDst((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_DST;
+                    break;
+                case SCTP_SRC:
+                    setTcpSrc((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_SRC;
+                    break;
+                case TCP_DST:
+                    setTcpDst((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_DST;
+                    break;
+                case TCP_SRC:
+                    setTcpSrc((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_SRC;
+                    break;
+                case UDP_DST:
+                    setTcpDst((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_DST;
+                    break;
+                case UDP_SRC:
+                    setTcpSrc((TransportPort) value);
+                    wildcards &= ~OFPFW_TP_SRC;
+                    break;
+                case VLAN_PCP:
+                    setVlanPcp((VlanPcp) value);
+                    wildcards &= ~OFPFW_DL_VLAN_PCP;
+                    break;
+                case VLAN_VID:
+                    setVlanVid((OFVlanVidMatch) value);
+                    wildcards &= ~OFPFW_DL_VLAN;
+                    break;
+                default:
+                    throw new UnsupportedOperationException(
+                            "OFMatch does not support matching on field " + field.getName());
+            }
+            return this;
+        }
+
+        @Override
+        public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field,
+                F value, F mask) {
+            initWildcards();
+            switch (field.id) {
+                case ARP_SPA:
+                case ARP_TPA:
+                case IPV4_DST:
+                case IPV4_SRC:
+                    Object valObj = value;
+                    Object masObj = mask;
+                    IPv4Address ip = ((IPv4Address)valObj);
+                    int maskval = ((IPv4Address)masObj).getInt();
+                    if (Integer.bitCount(~maskval + 1) != 1)
+                        throw new UnsupportedOperationException("OFMatch only supports CIDR masks for IPv4");
+                    int maskLen = 32 - Integer.bitCount(maskval);
+                    switch(field.id) {
+                        case ARP_TPA:
+                        case IPV4_DST:
+                            setIpv4Dst(ip);
+                            wildcards = (wildcards &~OFPFW_NW_DST_MASK) | (maskLen << OFPFW_NW_DST_SHIFT);
+                            break;
+                        case ARP_SPA:
+                        case IPV4_SRC:
+                            setIpv4Src(ip);
+                            wildcards = (wildcards &~OFPFW_NW_SRC_MASK) | (maskLen << OFPFW_NW_SRC_SHIFT);
+                            break;
+                        default:
+                            // Cannot really get here
+                            break;
+                    }
+                    break;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+            }
+            return this;
+        }
+
+        @Override
+        public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field, Masked<F> valueWithMask)
+                                                                       throws UnsupportedOperationException {
+            return this.setMasked(field, valueWithMask.getValue(), valueWithMask.getMask());
+        }
+
+        @Override
+        public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+            initWildcards();
+            switch (field.id) {
+                case ETH_DST:
+                    setEthDst(MacAddress.NONE);
+                    wildcards |= OFPFW_DL_DST;
+                    break;
+                case ETH_SRC:
+                    setEthSrc(MacAddress.NONE);
+                    wildcards |= OFPFW_DL_SRC;
+                    break;
+                case ETH_TYPE:
+                    setEthType(EthType.NONE);
+                    wildcards |= OFPFW_DL_TYPE;
+                    break;
+                case ICMPV4_CODE:
+                case TCP_DST:
+                case UDP_DST:
+                case SCTP_DST:
+                    setTcpDst(TransportPort.NONE);
+                    wildcards |= OFPFW_TP_DST;
+                    break;
+                case ICMPV4_TYPE:
+                case TCP_SRC:
+                case UDP_SRC:
+                case SCTP_SRC:
+                    setTcpSrc(TransportPort.NONE);
+                    wildcards |= OFPFW_TP_SRC;
+                    break;
+                case IN_PORT:
+                    setInPort(OFPort.of(0)); // NOTE: not 'NONE' -- that is 0xFF for ports
+                    wildcards |= OFPFW_IN_PORT;
+                    break;
+                case ARP_TPA:
+                case IPV4_DST:
+                    setIpv4Dst(IPv4Address.NONE);
+                    wildcards |= OFPFW_NW_DST_MASK;
+                    break;
+                case ARP_SPA:
+                case IPV4_SRC:
+                    setIpv4Src(IPv4Address.NONE);
+                    wildcards |= OFPFW_NW_SRC_MASK;
+                    break;
+                case IP_DSCP:
+                    setIpDscp(IpDscp.NONE);
+                    wildcards |= OFPFW_NW_TOS;
+                    break;
+                case IP_PROTO:
+                    setIpProto(IpProtocol.NONE);
+                    wildcards |= OFPFW_NW_PROTO;
+                    break;
+                case VLAN_PCP:
+                    setVlanPcp(VlanPcp.NONE);
+                    wildcards |= OFPFW_DL_VLAN_PCP;
+                    break;
+                case VLAN_VID:
+                    setVlanVid(OFVlanVidMatch.NONE);
+                    wildcards |= OFPFW_DL_VLAN;
+                    break;
+                default:
+                    throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+            }
+            return this;
+        }
+
+    }
+
+
+    final static Reader READER = new Reader();
+    static class Reader implements OFMessageReader<OFMatchV1> {
+        @Override
+        public OFMatchV1 readFrom(ChannelBuffer bb) throws OFParseError {
+            int wildcards = bb.readInt();
+            OFPort inPort = OFPort.read2Bytes(bb);
+            MacAddress ethSrc = MacAddress.read6Bytes(bb);
+            MacAddress ethDst = MacAddress.read6Bytes(bb);
+            OFVlanVidMatch vlanVid = OFVlanVidMatch.read2BytesOF10(bb);
+            VlanPcp vlanPcp = VlanPcp.readByte(bb);
+            // pad: 1 bytes
+            bb.skipBytes(1);
+            EthType ethType = EthType.read2Bytes(bb);
+            IpDscp ipDscp = IpDscp.readByte(bb);
+            IpProtocol ipProto = IpProtocol.readByte(bb);
+            // pad: 2 bytes
+            bb.skipBytes(2);
+            IPv4Address ipv4Src = IPv4Address.read4Bytes(bb);
+            IPv4Address ipv4Dst = IPv4Address.read4Bytes(bb);
+            TransportPort tcpSrc = TransportPort.read2Bytes(bb);
+            TransportPort tcpDst = TransportPort.read2Bytes(bb);
+
+            // normalize match fields according to current OpenVSwitch behavior. When prerequisites for a field are not met
+            // e.g., eth_type is not set to 0x800, OVS sets the value of corresponding ignored fields (e.g.,
+            // ip_src, tcp_dst) to 0, and sets the wildcard bit to 1.
+            if(ethType.equals(EthType.IPv4)) {
+                // IP
+                if(ipProto.equals(IpProtocol.TCP) || ipProto.equals(IpProtocol.UDP) || ipProto.equals(IpProtocol.ICMP)) {
+                    // fully speced, wildcards and all values are fine
+                    // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                        wildcards |= OFPFW_NW_SRC_MASK;
+
+                    // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                        wildcards |= OFPFW_NW_DST_MASK;
+
+                } else {
+                    // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                        wildcards |= OFPFW_NW_SRC_MASK;
+
+                    // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                    if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                        wildcards |= OFPFW_NW_DST_MASK;
+
+                    // not TCP/UDP/ICMP -> Clear TP wildcards for the wire
+                    wildcards |= (OFPFW_TP_SRC | OFPFW_TP_DST);
+                    tcpSrc = TransportPort.NONE;
+                    tcpDst = TransportPort.NONE;
+                }
+            } else if (ethType.equals(EthType.ARP)) {
+                // normalize 32-63 ipv4 src 'mask' to a full bitmask
+                if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+                    wildcards |= OFPFW_NW_SRC_MASK;
+
+                // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+                if((wildcards & OFPFW_NW_DST_ALL) != 0)
+                    wildcards |= OFPFW_NW_DST_MASK;
+
+                // ARP: clear NW_TOS / TP wildcards for the wire
+                wildcards |= ( OFPFW_NW_TOS | OFPFW_TP_SRC | OFPFW_TP_DST);
+                ipDscp = IpDscp.NONE;
+                tcpSrc = TransportPort.NONE;
+                tcpDst = TransportPort.NONE;
+            } else {
+                // not even IP. Clear NW/TP wildcards for the wire
+                wildcards |= ( OFPFW_NW_TOS | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_TP_SRC | OFPFW_TP_DST);
+                ipDscp = IpDscp.NONE;
+                ipProto = IpProtocol.NONE;
+                ipv4Src = IPv4Address.NONE;
+                ipv4Dst = IPv4Address.NONE;
+                tcpSrc = TransportPort.NONE;
+                tcpDst = TransportPort.NONE;
+            }
+            OFMatchV1Ver10 matchV1Ver10 = new OFMatchV1Ver10(
+                    wildcards,
+                      inPort,
+                      ethSrc,
+                      ethDst,
+                      vlanVid,
+                      vlanPcp,
+                      ethType,
+                      ipDscp,
+                      ipProto,
+                      ipv4Src,
+                      ipv4Dst,
+                      tcpSrc,
+                      tcpDst
+                    );
+            if(logger.isTraceEnabled())
+                logger.trace("readFrom - read={}", matchV1Ver10);
+            return matchV1Ver10;
+        }
+    }
+
+    public void putTo(PrimitiveSink sink) {
+        FUNNEL.funnel(this, sink);
+    }
+
+    final static OFMatchV1Ver10Funnel FUNNEL = new OFMatchV1Ver10Funnel();
+    static class OFMatchV1Ver10Funnel implements Funnel<OFMatchV1Ver10> {
+        private static final long serialVersionUID = 1L;
+        @Override
+        public void funnel(OFMatchV1Ver10 message, PrimitiveSink sink) {
+            sink.putInt(message.wildcards);
+            message.inPort.putTo(sink);
+            message.ethSrc.putTo(sink);
+            message.ethDst.putTo(sink);
+            message.vlanVid.putTo(sink);
+            message.vlanPcp.putTo(sink);
+            // skip pad (1 bytes)
+            message.ethType.putTo(sink);
+            message.ipDscp.putTo(sink);
+            message.ipProto.putTo(sink);
+            // skip pad (2 bytes)
+            message.ipv4Src.putTo(sink);
+            message.ipv4Dst.putTo(sink);
+            message.tcpSrc.putTo(sink);
+            message.tcpDst.putTo(sink);
+        }
+    }
+
+
+    public void writeTo(ChannelBuffer bb) {
+        WRITER.write(bb, this);
+    }
+
+    final static Writer WRITER = new Writer();
+    static class Writer implements OFMessageWriter<OFMatchV1Ver10> {
+        @Override
+        public void write(ChannelBuffer bb, OFMatchV1Ver10 message) {
+            bb.writeInt(message.wildcards);
+            message.inPort.write2Bytes(bb);
+            message.ethSrc.write6Bytes(bb);
+            message.ethDst.write6Bytes(bb);
+            message.vlanVid.write2BytesOF10(bb);
+            message.vlanPcp.writeByte(bb);
+            // pad: 1 bytes
+            bb.writeZero(1);
+            message.ethType.write2Bytes(bb);
+            message.ipDscp.writeByte(bb);
+            message.ipProto.writeByte(bb);
+            // pad: 2 bytes
+            bb.writeZero(2);
+            message.ipv4Src.write4Bytes(bb);
+            message.ipv4Dst.write4Bytes(bb);
+            message.tcpSrc.write2Bytes(bb);
+            message.tcpDst.write2Bytes(bb);
+
+
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder b = new StringBuilder("OFMatchV1Ver10(");
+        boolean first = true;
+        for(MatchField<?> field : getMatchFields()) {
+            if(first)
+                first = false;
+            else
+                b.append(", ");
+            String name = field.getName();
+            b.append(name).append('=').append(this.get(field));
+            if(isPartiallyMasked(field)) {
+                b.append('/').append(this.getMasked(field).getMask());
+            }
+        }
+        b.append(")");
+        return b.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        OFMatchV1Ver10 other = (OFMatchV1Ver10) obj;
+
+        if( wildcards != other.wildcards)
+            return false;
+        if (inPort == null) {
+            if (other.inPort != null)
+                return false;
+        } else if (!inPort.equals(other.inPort))
+            return false;
+        if (ethSrc == null) {
+            if (other.ethSrc != null)
+                return false;
+        } else if (!ethSrc.equals(other.ethSrc))
+            return false;
+        if (ethDst == null) {
+            if (other.ethDst != null)
+                return false;
+        } else if (!ethDst.equals(other.ethDst))
+            return false;
+        if (vlanVid == null) {
+            if (other.vlanVid != null)
+                return false;
+        } else if (!vlanVid.equals(other.vlanVid))
+            return false;
+        if (vlanPcp == null) {
+            if (other.vlanPcp != null)
+                return false;
+        } else if (!vlanPcp.equals(other.vlanPcp))
+            return false;
+        if (ethType == null) {
+            if (other.ethType != null)
+                return false;
+        } else if (!ethType.equals(other.ethType))
+            return false;
+        if (ipDscp == null) {
+            if (other.ipDscp != null)
+                return false;
+        } else if (!ipDscp.equals(other.ipDscp))
+            return false;
+        if (ipProto == null) {
+            if (other.ipProto != null)
+                return false;
+        } else if (!ipProto.equals(other.ipProto))
+            return false;
+        if (ipv4Src == null) {
+            if (other.ipv4Src != null)
+                return false;
+        } else if (!ipv4Src.equals(other.ipv4Src))
+            return false;
+        if (ipv4Dst == null) {
+            if (other.ipv4Dst != null)
+                return false;
+        } else if (!ipv4Dst.equals(other.ipv4Dst))
+            return false;
+        if (tcpSrc == null) {
+            if (other.tcpSrc != null)
+                return false;
+        } else if (!tcpSrc.equals(other.tcpSrc))
+            return false;
+        if (tcpDst == null) {
+            if (other.tcpDst != null)
+                return false;
+        } else if (!tcpDst.equals(other.tcpDst))
+            return false;
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+
+        result = prime * result + wildcards;
+        result = prime * result + ((inPort == null) ? 0 : inPort.hashCode());
+        result = prime * result + ((ethSrc == null) ? 0 : ethSrc.hashCode());
+        result = prime * result + ((ethDst == null) ? 0 : ethDst.hashCode());
+        result = prime * result + ((vlanVid == null) ? 0 : vlanVid.hashCode());
+        result = prime * result + ((vlanPcp == null) ? 0 : vlanPcp.hashCode());
+        result = prime * result + ((ethType == null) ? 0 : ethType.hashCode());
+        result = prime * result + ((ipDscp == null) ? 0 : ipDscp.hashCode());
+        result = prime * result + ((ipProto == null) ? 0 : ipProto.hashCode());
+        result = prime * result + ((ipv4Src == null) ? 0 : ipv4Src.hashCode());
+        result = prime * result + ((ipv4Dst == null) ? 0 : ipv4Dst.hashCode());
+        result = prime * result + ((tcpSrc == null) ? 0 : tcpSrc.hashCode());
+        result = prime * result + ((tcpDst == null) ? 0 : tcpDst.hashCode());
+        return result;
+    }
+
+}