Bug-5119 - Adding support for L3 address arbitraty bit mask with Unittests coverage...
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / match / MatchConvertorImpl.java
index f6b556d426b24daa76cfca912f6ad527666938bb..a78f48968b8844b17180c0219bc51f80edfc1f1a 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2013-2015 Ericsson. and others.  All rights reserved.
+ * Copyright (c) 20132015 Ericsson. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -15,6 +15,7 @@ import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import javax.annotation.Nonnull;
 import org.opendaylight.openflowjava.util.ByteBufUtils;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
@@ -27,15 +28,16 @@ import org.opendaylight.openflowplugin.openflow.md.util.ActionUtil;
 import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IetfInetUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6FlowLabel;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetField;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
@@ -64,18 +66,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.MetadataBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFields;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFieldsBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
@@ -273,7 +267,20 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
     private static final short PROTO_TCP = 6;
     private static final short PROTO_UDP = 17;
     private static final short PROTO_ICMPV4 = 1;
-    private static final String noIp = "0.0.0.0/0";
+    private static final String NO_IP = "0.0.0.0/0";
+
+    // Pre-calculated masks for the 33 possible values. Do not give them out, but clone() them as they may
+    // end up being leaked and vulnerable.
+    private static final byte[][] IPV4_MASKS;
+    static {
+        final byte[][] tmp = new byte[33][];
+        for (int i = 0; i <= 32; ++i) {
+            final int mask = 0xffffffff << (32 - i);
+            tmp[i] =  new byte[]{(byte) (mask >>> 24), (byte) (mask >>> 16), (byte) (mask >>> 8), (byte) mask};
+        }
+
+        IPV4_MASKS = tmp;
+    }
 
     @Override
     public List<MatchEntry> convert(
@@ -300,224 +307,133 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
             matchEntryList.add(toOfMetadata(Metadata.class, metadata.getMetadata(), metadata.getMetadataMask()));
         }
 
-        EthernetMatch ethernetMatch = match.getEthernetMatch();
-        if (ethernetMatch != null) {
-            EthernetDestination ethernetDestination = ethernetMatch.getEthernetDestination();
-            if (ethernetDestination != null) {
-                MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-                matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                matchEntryBuilder.setOxmMatchField(EthDst.class);
-                EthDstCaseBuilder ethDstCaseBuilder = new EthDstCaseBuilder();
-                EthDstBuilder ethDstBuilder = new EthDstBuilder();
-                ethDstBuilder.setMacAddress(ethernetDestination.getAddress());
-                boolean hasMask = false;
-                if (null != ethernetDestination.getMask()) {
-                    ethDstBuilder.setMask(ByteBufUtils.macAddressToBytes(ethernetDestination.getMask().getValue()));
-                    hasMask = true;
-                }
-                ethDstCaseBuilder.setEthDst(ethDstBuilder.build());
-                matchEntryBuilder.setMatchEntryValue(ethDstCaseBuilder.build());
-                matchEntryBuilder.setHasMask(hasMask);
-                matchEntryList.add(matchEntryBuilder.build());
-            }
+        ethernetMatch(matchEntryList, match.getEthernetMatch());
+        vlanMatch(matchEntryList, match.getVlanMatch());
+        ipMatch(matchEntryList, match.getIpMatch());
+        layer4Match(matchEntryList, match.getLayer4Match());
+        icmpv4Match(matchEntryList, match.getIcmpv4Match());
+        icmpv6Match(matchEntryList, match.getIcmpv6Match());
+        layer3Match(matchEntryList, match.getLayer3Match());
+        protocolMatchFields(matchEntryList, match.getProtocolMatchFields());
 
-            EthernetSource ethernetSource = ethernetMatch.getEthernetSource();
-            if (ethernetSource != null) {
-                MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-                matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                matchEntryBuilder.setOxmMatchField(EthSrc.class);
-
-                EthSrcCaseBuilder ethSrcCaseBuilder = new EthSrcCaseBuilder();
-                EthSrcBuilder ethDstBuilder = new EthSrcBuilder();
-                ethDstBuilder.setMacAddress(ethernetSource.getAddress());
-                boolean hasMask = false;
-                if (null != ethernetSource.getMask()) {
-                    ethDstBuilder.setMask(ByteBufUtils.macAddressToBytes(ethernetSource.getMask().getValue()));
-                    hasMask = true;
-                }
-                ethSrcCaseBuilder.setEthSrc(ethDstBuilder.build());
-                matchEntryBuilder.setMatchEntryValue(ethSrcCaseBuilder.build());
-                matchEntryBuilder.setHasMask(hasMask);
-                matchEntryList.add(matchEntryBuilder.build());
+        org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Tunnel tunnel = match
+                .getTunnel();
+        if (tunnel != null) {
+            MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+            TunnelIdCaseBuilder tunnelIdCaseBuilder = new TunnelIdCaseBuilder();
+            TunnelIdBuilder tunnelIdBuilder = new TunnelIdBuilder();
+            boolean hasMask = false;
+            if (null != tunnel.getTunnelMask()) {
+                hasMask = true;
+                tunnelIdBuilder.setMask(ByteUtil.convertBigIntegerToNBytes(tunnel.getTunnelMask(), OFConstants.SIZE_OF_LONG_IN_BYTES));
             }
+            tunnelIdBuilder.setTunnelId(ByteUtil.convertBigIntegerToNBytes(tunnel.getTunnelId(), OFConstants.SIZE_OF_LONG_IN_BYTES));
+            tunnelIdCaseBuilder.setTunnelId(tunnelIdBuilder.build());
+            matchEntryBuilder.setMatchEntryValue(tunnelIdCaseBuilder.build());
+            matchEntryBuilder.setHasMask(hasMask);
+            matchEntryBuilder.setOxmMatchField(TunnelId.class);
+            matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+            matchEntryList.add(matchEntryBuilder.build());
+        }
 
-            if (ethernetMatch.getEthernetType() != null) {
-                matchEntryList.add(toOfEthernetType(ethernetMatch.getEthernetType()));
+
+        /**
+         * TODO: EXTENSION PROPOSAL (match, MD-SAL to OFJava)
+         * - we might need version for conversion and for key
+         * - sanitize NPE
+         */
+        Optional<GeneralExtensionListGrouping> extensionListOpt = ExtensionResolvers.getMatchExtensionResolver().getExtension(match);
+        if (extensionListOpt.isPresent()) {
+            for (ExtensionList extensionItem : extensionListOpt.get().getExtensionList()) {
+                // TODO: get real version
+                ConverterExtensionKey<? extends ExtensionKey> key = new ConverterExtensionKey<>(extensionItem.getExtensionKey(), OFConstants.OFP_VERSION_1_3);
+                ConvertorToOFJava<MatchEntry> convertor =
+                        OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
+                MatchEntry ofMatch = convertor.convert(extensionItem.getExtension());
+                matchEntryList.add(ofMatch);
             }
         }
 
-        VlanMatch vlanMatch = match.getVlanMatch();
-        if (vlanMatch != null) {
-            if (vlanMatch.getVlanId() != null) {
-                VlanId vlanId = vlanMatch.getVlanId();
-                MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-                matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                matchEntryBuilder.setOxmMatchField(VlanVid.class);
-
-                VlanVidCaseBuilder vlanVidCaseBuilder = new VlanVidCaseBuilder();
-                VlanVidBuilder vlanVidBuilder = new VlanVidBuilder();
-                boolean setCfiBit = false;
-                Integer vidEntryValue = 0;
-                boolean hasmask = false;
-                if (Boolean.TRUE.equals(vlanId.isVlanIdPresent())) {
-                    setCfiBit = true;
-                    if (vlanId.getVlanId() != null) {
-                        vidEntryValue = vlanId.getVlanId().getValue();
-                    }
-                    hasmask = (vidEntryValue == 0);
-                    if (hasmask) {
-                        vlanVidBuilder.setMask(VLAN_VID_MASK);
-                    }
-                }
+        return matchEntryList;
+    }
 
-                vlanVidBuilder.setCfiBit(setCfiBit);
-                vlanVidBuilder.setVlanVid(vidEntryValue);
-                vlanVidCaseBuilder.setVlanVid(vlanVidBuilder.build());
-                matchEntryBuilder.setMatchEntryValue(vlanVidCaseBuilder.build());
-                matchEntryBuilder.setHasMask(hasmask);
-                matchEntryList.add(matchEntryBuilder.build());
-            }
 
-            if (vlanMatch.getVlanPcp() != null) {
-                matchEntryList.add(toOfVlanPcp(vlanMatch.getVlanPcp()));
+    private static void protocolMatchFields(final List<MatchEntry> matchEntryList,
+            final ProtocolMatchFields protocolMatchFields) {
+        if (protocolMatchFields != null) {
+            if (protocolMatchFields.getMplsLabel() != null) {
+                matchEntryList.add(toOfMplsLabel(protocolMatchFields.getMplsLabel()));
             }
-        }
 
-        IpMatch ipMatch = match.getIpMatch();
-        if (ipMatch != null) {
-            if (ipMatch.getIpDscp() != null) {
-                matchEntryList.add(toOfIpDscp(ipMatch.getIpDscp()));
+            if (protocolMatchFields.getMplsBos() != null) {
+                matchEntryList.add(toOfMplsBos(protocolMatchFields.getMplsBos()));
             }
 
-            if (ipMatch.getIpEcn() != null) {
-                matchEntryList.add(toOfIpEcn(ipMatch.getIpEcn()));
+            if (protocolMatchFields.getMplsTc() != null) {
+                matchEntryList.add(toOfMplsTc(protocolMatchFields.getMplsTc()));
             }
 
-            if (ipMatch.getIpProtocol() != null) {
-                matchEntryList.add(toOfIpProto(ipMatch.getIpProtocol()));
+            if (protocolMatchFields.getPbb() != null) {
+                matchEntryList.add(toOfMplsPbb(protocolMatchFields.getPbb()));
             }
-
         }
+    }
 
-        Layer4Match layer4Match = match.getLayer4Match();
-        if (layer4Match != null) {
-            if (layer4Match instanceof TcpMatch) {
-                TcpMatch tcpMatch = (TcpMatch) layer4Match;
 
-                if (tcpMatch.getTcpSourcePort() != null) {
+    private static void layer3Match(final List<MatchEntry> matchEntryList, final Layer3Match layer3Match) {
+        if (layer3Match != null) {
+            if(layer3Match instanceof Ipv4MatchArbitraryBitMask) {
+                Ipv4MatchArbitraryBitMask ipv4MatchArbitraryBitMaskFields = (Ipv4MatchArbitraryBitMask) layer3Match;
+                if (ipv4MatchArbitraryBitMaskFields.getIpv4SourceAddressNoMask() != null) {
                     MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
                     matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(TcpSrc.class);
-
-                    TcpSrcCaseBuilder tcpSrcCaseBuilder = new TcpSrcCaseBuilder();
-                    TcpSrcBuilder tcpSrcBuilder = new TcpSrcBuilder();
-                    tcpSrcBuilder.setPort(tcpMatch.getTcpSourcePort());
-                    tcpSrcCaseBuilder.setTcpSrc(tcpSrcBuilder.build());
+                    matchEntryBuilder.setOxmMatchField(Ipv4Src.class);
 
-                    matchEntryBuilder.setMatchEntryValue(tcpSrcCaseBuilder.build());
-                    matchEntryBuilder.setHasMask(false);
-                    matchEntryList.add(matchEntryBuilder.build());
-                }
-                if (tcpMatch.getTcpDestinationPort() != null) {
-                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(TcpDst.class);
+                    Ipv4SrcCaseBuilder ipv4SrcCaseBuilder = new Ipv4SrcCaseBuilder();
+                    Ipv4SrcBuilder ipv4SrcBuilder = new Ipv4SrcBuilder();
 
-                    TcpDstCaseBuilder tcpDstCaseBuilder = new TcpDstCaseBuilder();
-                    TcpDstBuilder tcpDstBuilder = new TcpDstBuilder();
-                    tcpDstBuilder.setPort(tcpMatch.getTcpDestinationPort());
-                    tcpDstCaseBuilder.setTcpDst(tcpDstBuilder.build());
-                    matchEntryBuilder.setMatchEntryValue(tcpDstCaseBuilder.build());
-                    matchEntryBuilder.setHasMask(false);
-                    matchEntryList.add(matchEntryBuilder.build());
-                }
-            } else if (layer4Match instanceof UdpMatch) {
-                UdpMatch udpMatch = (UdpMatch) layer4Match;
-                if (udpMatch.getUdpSourcePort() != null) {
-                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(UdpSrc.class);
+                    ipv4SrcBuilder.setIpv4Address(ipv4MatchArbitraryBitMaskFields.getIpv4SourceAddressNoMask());
+                    DottedQuad sourceArbitrarySubNetMask = ipv4MatchArbitraryBitMaskFields.getIpv4SourceArbitraryBitmask();
 
-                    UdpSrcCaseBuilder udpSrcCaseBuilder = new UdpSrcCaseBuilder();
-                    UdpSrcBuilder udpSrcBuilder = new UdpSrcBuilder();
                     boolean hasMask = false;
-                    udpSrcBuilder.setPort(udpMatch.getUdpSourcePort());
-                    udpSrcCaseBuilder.setUdpSrc(udpSrcBuilder.build());
-                    matchEntryBuilder.setMatchEntryValue(udpSrcCaseBuilder.build());
+                    if (sourceArbitrarySubNetMask != null) {
+                        byte[] maskByteArray = IpConversionUtil.convertArbitraryMaskToByteArray(sourceArbitrarySubNetMask);
+                        if (maskByteArray != null) {
+                            ipv4SrcBuilder.setMask(maskByteArray);
+                            hasMask = true;
+                        }
+                    }
                     matchEntryBuilder.setHasMask(hasMask);
+                    ipv4SrcCaseBuilder.setIpv4Src(ipv4SrcBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(ipv4SrcCaseBuilder.build());
                     matchEntryList.add(matchEntryBuilder.build());
                 }
-
-                if (udpMatch.getUdpDestinationPort() != null) {
+                if (ipv4MatchArbitraryBitMaskFields.getIpv4DestinationAddressNoMask() != null) {
                     MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
                     matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(UdpDst.class);
-
-                    UdpDstCaseBuilder udpDstCaseBuilder = new UdpDstCaseBuilder();
-                    UdpDstBuilder udpDstBuilder = new UdpDstBuilder();
-                    udpDstBuilder.setPort(udpMatch.getUdpDestinationPort());
-                    udpDstCaseBuilder.setUdpDst(udpDstBuilder.build());
-                    matchEntryBuilder.setMatchEntryValue(udpDstCaseBuilder.build());
-                    matchEntryBuilder.setHasMask(false);
-                    matchEntryList.add(matchEntryBuilder.build());
-                }
-            } else if (layer4Match instanceof SctpMatch) {
-                SctpMatch sctpMatch = (SctpMatch) layer4Match;
-                if (sctpMatch.getSctpSourcePort() != null) {
-                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(SctpSrc.class);
+                    matchEntryBuilder.setOxmMatchField(Ipv4Dst.class);
 
-                    SctpSrcCaseBuilder sctpSrcCaseBuilder = new SctpSrcCaseBuilder();
-                    SctpSrcBuilder sctpSrcBuilder = new SctpSrcBuilder();
-                    sctpSrcBuilder.setPort(sctpMatch.getSctpSourcePort());
-                    sctpSrcCaseBuilder.setSctpSrc(sctpSrcBuilder.build());
-                    matchEntryBuilder.setMatchEntryValue(sctpSrcCaseBuilder.build());
-                    matchEntryBuilder.setHasMask(false);
-                    matchEntryList.add(matchEntryBuilder.build());
-                }
+                    Ipv4DstCaseBuilder ipv4DstCaseBuilder = new Ipv4DstCaseBuilder();
+                    Ipv4DstBuilder ipv4DstBuilder = new Ipv4DstBuilder();
 
-                if (sctpMatch.getSctpDestinationPort() != null) {
-                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(SctpDst.class);
+                    ipv4DstBuilder.setIpv4Address(ipv4MatchArbitraryBitMaskFields.getIpv4DestinationAddressNoMask());
+                    DottedQuad destArbitrarySubNetMask = ipv4MatchArbitraryBitMaskFields.getIpv4DestinationArbitraryBitmask();
 
-                    SctpDstCaseBuilder sctpDstCaseBuilder = new SctpDstCaseBuilder();
-                    SctpDstBuilder sctpDstBuilder = new SctpDstBuilder();
-                    sctpDstBuilder.setPort(sctpMatch.getSctpDestinationPort());
-                    sctpDstCaseBuilder.setSctpDst(sctpDstBuilder.build());
-                    matchEntryBuilder.setMatchEntryValue(sctpDstCaseBuilder.build());
-                    matchEntryBuilder.setHasMask(false);
+                    boolean hasMask = false;
+                    if (destArbitrarySubNetMask != null) {
+                        byte[] maskByteArray = IpConversionUtil.convertArbitraryMaskToByteArray(destArbitrarySubNetMask);
+                        if (maskByteArray != null) {
+                            ipv4DstBuilder.setMask(maskByteArray);
+                            hasMask = true;
+                        }
+                    }
+                    matchEntryBuilder.setHasMask(hasMask);
+                    ipv4DstCaseBuilder.setIpv4Dst(ipv4DstBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(ipv4DstCaseBuilder.build());
                     matchEntryList.add(matchEntryBuilder.build());
                 }
             }
-        }
-
-        Icmpv4Match icmpv4Match = match.getIcmpv4Match();
-        if (icmpv4Match != null) {
-            if (icmpv4Match.getIcmpv4Type() != null) {
-                matchEntryList.add(toOfIcmpv4Type(icmpv4Match.getIcmpv4Type()));
-            }
-
-            if (icmpv4Match.getIcmpv4Code() != null) {
-                matchEntryList.add(toOfIcmpv4Code(icmpv4Match.getIcmpv4Code()));
-            }
-        }
-
-        Icmpv6Match icmpv6Match = match.getIcmpv6Match();
-        if (icmpv6Match != null) {
-            if (icmpv6Match.getIcmpv6Type() != null) {
-                matchEntryList.add(toOfIcmpv6Type(icmpv6Match.getIcmpv6Type()));
-            }
-
-            if (icmpv6Match.getIcmpv6Code() != null) {
-                matchEntryList.add(toOfIcmpv6Code(icmpv6Match.getIcmpv6Code()));
-            }
-        }
-
-        Layer3Match layer3Match = match.getLayer3Match();
-        if (layer3Match != null) {
-            if (layer3Match instanceof Ipv4Match) {
+            if(layer3Match instanceof Ipv4Match){
                 Ipv4Match ipv4Match = (Ipv4Match) layer3Match;
                 if (ipv4Match.getIpv4Source() != null) {
                     Ipv4Prefix ipv4Prefix = ipv4Match.getIpv4Source();
@@ -532,7 +448,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                     Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
                     ipv4SrcBuilder.setIpv4Address(ipv4Address);
                     boolean hasMask = false;
-                    byte[] mask = extractIpv4Mask(hasMask, addressParts);
+                    byte[] mask = extractIpv4Mask(addressParts);
                     if (null != mask) {
                         ipv4SrcBuilder.setMask(mask);
                         hasMask = true;
@@ -555,7 +471,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                     Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
                     ipv4DstBuilder.setIpv4Address(ipv4Address);
                     boolean hasMask = false;
-                    byte[] mask = extractIpv4Mask(hasMask, addressParts);
+                    byte[] mask = extractIpv4Mask(addressParts);
                     if (null != mask) {
                         ipv4DstBuilder.setMask(mask);
                         hasMask = true;
@@ -581,7 +497,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                     Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
                     ipv4SrcBuilder.setIpv4Address(ipv4Address);
                     boolean hasMask = false;
-                    byte[] mask = extractIpv4Mask(hasMask, addressParts);
+                    byte[] mask = extractIpv4Mask(addressParts);
                     if (null != mask) {
                         ipv4SrcBuilder.setMask(mask);
                         hasMask = true;
@@ -604,7 +520,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                     Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
                     ipv4DstBuilder.setIpv4Address(ipv4Address);
                     boolean hasMask = false;
-                    byte[] mask = extractIpv4Mask(hasMask, addressParts);
+                    byte[] mask = extractIpv4Mask(addressParts);
                     if (null != mask) {
                         ipv4DstBuilder.setMask(mask);
                         hasMask = true;
@@ -633,7 +549,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                     Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
                     arpSpaBuilder.setIpv4Address(ipv4Address);
                     boolean hasMask = false;
-                    byte[] mask = extractIpv4Mask(hasMask, addressParts);
+                    byte[] mask = extractIpv4Mask(addressParts);
                     if (null != mask) {
                         arpSpaBuilder.setMask(mask);
                         hasMask = true;
@@ -657,7 +573,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                     Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
                     arpTpaBuilder.setIpv4Address(ipv4Address);
                     boolean hasMask = false;
-                    byte[] mask = extractIpv4Mask(hasMask, addressParts);
+                    byte[] mask = extractIpv4Mask(addressParts);
                     if (null != mask) {
                         arpTpaBuilder.setMask(mask);
                         hasMask = true;
@@ -698,7 +614,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                     ArpThaBuilder arpThaBuilder = new ArpThaBuilder();
                     arpThaBuilder.setMacAddress(arpTargetHardwareAddress.getAddress());
                     boolean hasMask = false;
-                    if (null != arpSourceHardwareAddress.getMask()) {
+                    if (null != arpTargetHardwareAddress.getMask()) {
                         arpThaBuilder.setMask(ByteBufUtils.macAddressToBytes(arpTargetHardwareAddress.getMask().getValue()));
                         hasMask = true;
                     }
@@ -713,153 +629,318 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                     Ipv6Prefix ipv6Prefix = ipv6Match.getIpv6Source();
                     MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
                     matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(Ipv6Src.class);
+                    matchEntryBuilder.setOxmMatchField(Ipv6Src.class);
+
+                    Ipv6SrcCaseBuilder ipv6SrcCaseBuilder = new Ipv6SrcCaseBuilder();
+                    Ipv6SrcBuilder ipv6SrcBuilder = new Ipv6SrcBuilder();
+                    final Integer prefix = IpConversionUtil.extractIpv6Prefix(ipv6Prefix);
+                    boolean hasMask = false;
+                    if (null != prefix) {
+                        ipv6SrcBuilder.setMask(IpConversionUtil.convertIpv6PrefixToByteArray(prefix));
+                        hasMask = true;
+                    }
+                    ipv6SrcBuilder.setIpv6Address(IpConversionUtil.extractIpv6Address(ipv6Prefix));
+                    ipv6SrcCaseBuilder.setIpv6Src(ipv6SrcBuilder.build());
+                    matchEntryBuilder.setHasMask(hasMask);
+                    matchEntryBuilder.setMatchEntryValue(ipv6SrcCaseBuilder.build());
+                    matchEntryList.add(matchEntryBuilder.build());
+                }
+
+                if (ipv6Match.getIpv6Destination() != null) {
+                    Ipv6Prefix ipv6Prefix = ipv6Match.getIpv6Destination();
+                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                    matchEntryBuilder.setOxmMatchField(Ipv6Dst.class);
+
+                    Ipv6DstCaseBuilder ipv6DstCaseBuilder = new Ipv6DstCaseBuilder();
+                    Ipv6DstBuilder ipv6DstBuilder = new Ipv6DstBuilder();
+                    final Integer prefix = IpConversionUtil.extractIpv6Prefix(ipv6Prefix);
+                    boolean hasMask = false;
+                    if (null != prefix) {
+                        ipv6DstBuilder.setMask(IpConversionUtil.convertIpv6PrefixToByteArray(prefix));
+                        hasMask = true;
+                    }
+                    ipv6DstBuilder.setIpv6Address(IpConversionUtil.extractIpv6Address(ipv6Prefix));
+                    ipv6DstCaseBuilder.setIpv6Dst(ipv6DstBuilder.build());
+                    matchEntryBuilder.setHasMask(hasMask);
+                    matchEntryBuilder.setMatchEntryValue(ipv6DstCaseBuilder.build());
+                    matchEntryList.add(matchEntryBuilder.build());
+                }
+
+                if (ipv6Match.getIpv6Label() != null) {
+                    matchEntryList.add(toOfIpv6FlowLabel(ipv6Match.getIpv6Label()));
+                }
+
+                if (ipv6Match.getIpv6NdTarget() != null) {
+                    matchEntryList.add(toOfIpv6NdTargetAddress(ipv6Match.getIpv6NdTarget()));
+                }
+
+                if (ipv6Match.getIpv6NdSll() != null) {
+                    MacAddress ipv6NdSll = ipv6Match.getIpv6NdSll();
+                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                    matchEntryBuilder.setOxmMatchField(Ipv6NdSll.class);
+
+                    Ipv6NdSllCaseBuilder ipv6NdSllCaseBuilder = new Ipv6NdSllCaseBuilder();
+                    Ipv6NdSllBuilder ipv6NdSllBuilder = new Ipv6NdSllBuilder();
+                    ipv6NdSllBuilder.setMacAddress(ipv6NdSll);
+                    ipv6NdSllCaseBuilder.setIpv6NdSll(ipv6NdSllBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(ipv6NdSllCaseBuilder.build());
+                    matchEntryBuilder.setHasMask(false);
+                    matchEntryList.add(matchEntryBuilder.build());
+                }
+
+                if (ipv6Match.getIpv6NdTll() != null) {
+                    MacAddress ipv6NdSll = ipv6Match.getIpv6NdTll();
+                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                    matchEntryBuilder.setOxmMatchField(Ipv6NdTll.class);
+
+                    Ipv6NdTllCaseBuilder ipv6NdTllCaseBuilder = new Ipv6NdTllCaseBuilder();
+                    Ipv6NdTllBuilder ipv6NdTllBuilder = new Ipv6NdTllBuilder();
+                    ipv6NdTllBuilder.setMacAddress(ipv6NdSll);
+                    ipv6NdTllCaseBuilder.setIpv6NdTll(ipv6NdTllBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(ipv6NdTllCaseBuilder.build());
+                    matchEntryBuilder.setHasMask(false);
+                    matchEntryList.add(matchEntryBuilder.build());
+
+                }
+
+                if (ipv6Match.getIpv6ExtHeader() != null) {
+                    matchEntryList.add(toOfIpv6ExtHeader(ipv6Match.getIpv6ExtHeader()));
+                }
+            }
+        }
+    }
+
+
+    private static void icmpv6Match(final List<MatchEntry> matchEntryList, final Icmpv6Match icmpv6Match) {
+        if (icmpv6Match != null) {
+            if (icmpv6Match.getIcmpv6Type() != null) {
+                matchEntryList.add(toOfIcmpv6Type(icmpv6Match.getIcmpv6Type()));
+            }
+
+            if (icmpv6Match.getIcmpv6Code() != null) {
+                matchEntryList.add(toOfIcmpv6Code(icmpv6Match.getIcmpv6Code()));
+            }
+        }
+    }
+
+
+    private static void icmpv4Match(final List<MatchEntry> matchEntryList, final Icmpv4Match icmpv4Match) {
+        if (icmpv4Match != null) {
+            if (icmpv4Match.getIcmpv4Type() != null) {
+                matchEntryList.add(toOfIcmpv4Type(icmpv4Match.getIcmpv4Type()));
+            }
+
+            if (icmpv4Match.getIcmpv4Code() != null) {
+                matchEntryList.add(toOfIcmpv4Code(icmpv4Match.getIcmpv4Code()));
+            }
+        }
+    }
+
+
+    private static void layer4Match(final List<MatchEntry> matchEntryList, final Layer4Match layer4Match) {
+        if (layer4Match != null) {
+            if (layer4Match instanceof TcpMatch) {
+                TcpMatch tcpMatch = (TcpMatch) layer4Match;
+
+                if (tcpMatch.getTcpSourcePort() != null) {
+                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                    matchEntryBuilder.setOxmMatchField(TcpSrc.class);
+
+                    TcpSrcCaseBuilder tcpSrcCaseBuilder = new TcpSrcCaseBuilder();
+                    TcpSrcBuilder tcpSrcBuilder = new TcpSrcBuilder();
+                    tcpSrcBuilder.setPort(tcpMatch.getTcpSourcePort());
+                    tcpSrcCaseBuilder.setTcpSrc(tcpSrcBuilder.build());
+
+                    matchEntryBuilder.setMatchEntryValue(tcpSrcCaseBuilder.build());
+                    matchEntryBuilder.setHasMask(false);
+                    matchEntryList.add(matchEntryBuilder.build());
+                }
+                if (tcpMatch.getTcpDestinationPort() != null) {
+                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                    matchEntryBuilder.setOxmMatchField(TcpDst.class);
 
-                    Ipv6SrcCaseBuilder ipv6SrcCaseBuilder = new Ipv6SrcCaseBuilder();
-                    Ipv6SrcBuilder ipv6SrcBuilder = new Ipv6SrcBuilder();
-                    final Integer prefix = IpConversionUtil.extractIpv6Prefix(ipv6Prefix);
-                    boolean hasMask = false;
-                    if (null != prefix) {
-                        ipv6SrcBuilder.setMask(IpConversionUtil.convertIpv6PrefixToByteArray(prefix));
-                        hasMask = true;
-                    }
-                    ipv6SrcBuilder.setIpv6Address(IpConversionUtil.extractIpv6Address(ipv6Prefix));
-                    ipv6SrcCaseBuilder.setIpv6Src(ipv6SrcBuilder.build());
-                    matchEntryBuilder.setHasMask(hasMask);
-                    matchEntryBuilder.setMatchEntryValue(ipv6SrcCaseBuilder.build());
+                    TcpDstCaseBuilder tcpDstCaseBuilder = new TcpDstCaseBuilder();
+                    TcpDstBuilder tcpDstBuilder = new TcpDstBuilder();
+                    tcpDstBuilder.setPort(tcpMatch.getTcpDestinationPort());
+                    tcpDstCaseBuilder.setTcpDst(tcpDstBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(tcpDstCaseBuilder.build());
+                    matchEntryBuilder.setHasMask(false);
                     matchEntryList.add(matchEntryBuilder.build());
                 }
-
-                if (ipv6Match.getIpv6Destination() != null) {
-                    Ipv6Prefix ipv6Prefix = ipv6Match.getIpv6Destination();
+            } else if (layer4Match instanceof UdpMatch) {
+                UdpMatch udpMatch = (UdpMatch) layer4Match;
+                if (udpMatch.getUdpSourcePort() != null) {
                     MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
                     matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(Ipv6Dst.class);
+                    matchEntryBuilder.setOxmMatchField(UdpSrc.class);
 
-                    Ipv6DstCaseBuilder ipv6DstCaseBuilder = new Ipv6DstCaseBuilder();
-                    Ipv6DstBuilder ipv6DstBuilder = new Ipv6DstBuilder();
-                    final Integer prefix = IpConversionUtil.extractIpv6Prefix(ipv6Prefix);
+                    UdpSrcCaseBuilder udpSrcCaseBuilder = new UdpSrcCaseBuilder();
+                    UdpSrcBuilder udpSrcBuilder = new UdpSrcBuilder();
                     boolean hasMask = false;
-                    if (null != prefix) {
-                        ipv6DstBuilder.setMask(IpConversionUtil.convertIpv6PrefixToByteArray(prefix));
-                        hasMask = true;
-                    }
-                    ipv6DstBuilder.setIpv6Address(IpConversionUtil.extractIpv6Address(ipv6Prefix));
-                    ipv6DstCaseBuilder.setIpv6Dst(ipv6DstBuilder.build());
+                    udpSrcBuilder.setPort(udpMatch.getUdpSourcePort());
+                    udpSrcCaseBuilder.setUdpSrc(udpSrcBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(udpSrcCaseBuilder.build());
                     matchEntryBuilder.setHasMask(hasMask);
-                    matchEntryBuilder.setMatchEntryValue(ipv6DstCaseBuilder.build());
                     matchEntryList.add(matchEntryBuilder.build());
                 }
 
-                if (ipv6Match.getIpv6Label() != null) {
-                    matchEntryList.add(toOfIpv6FlowLabel(ipv6Match.getIpv6Label()));
-                }
+                if (udpMatch.getUdpDestinationPort() != null) {
+                    MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                    matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                    matchEntryBuilder.setOxmMatchField(UdpDst.class);
 
-                if (ipv6Match.getIpv6NdTarget() != null) {
-                    matchEntryList.add(toOfIpv6NdTargetAddress(ipv6Match.getIpv6NdTarget()));
+                    UdpDstCaseBuilder udpDstCaseBuilder = new UdpDstCaseBuilder();
+                    UdpDstBuilder udpDstBuilder = new UdpDstBuilder();
+                    udpDstBuilder.setPort(udpMatch.getUdpDestinationPort());
+                    udpDstCaseBuilder.setUdpDst(udpDstBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(udpDstCaseBuilder.build());
+                    matchEntryBuilder.setHasMask(false);
+                    matchEntryList.add(matchEntryBuilder.build());
                 }
-
-                if (ipv6Match.getIpv6NdSll() != null) {
-                    MacAddress ipv6NdSll = ipv6Match.getIpv6NdSll();
+            } else if (layer4Match instanceof SctpMatch) {
+                SctpMatch sctpMatch = (SctpMatch) layer4Match;
+                if (sctpMatch.getSctpSourcePort() != null) {
                     MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
                     matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(Ipv6NdSll.class);
+                    matchEntryBuilder.setOxmMatchField(SctpSrc.class);
 
-                    Ipv6NdSllCaseBuilder ipv6NdSllCaseBuilder = new Ipv6NdSllCaseBuilder();
-                    Ipv6NdSllBuilder ipv6NdSllBuilder = new Ipv6NdSllBuilder();
-                    ipv6NdSllBuilder.setMacAddress(ipv6NdSll);
-                    ipv6NdSllCaseBuilder.setIpv6NdSll(ipv6NdSllBuilder.build());
-                    matchEntryBuilder.setMatchEntryValue(ipv6NdSllCaseBuilder.build());
+                    SctpSrcCaseBuilder sctpSrcCaseBuilder = new SctpSrcCaseBuilder();
+                    SctpSrcBuilder sctpSrcBuilder = new SctpSrcBuilder();
+                    sctpSrcBuilder.setPort(sctpMatch.getSctpSourcePort());
+                    sctpSrcCaseBuilder.setSctpSrc(sctpSrcBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(sctpSrcCaseBuilder.build());
                     matchEntryBuilder.setHasMask(false);
                     matchEntryList.add(matchEntryBuilder.build());
                 }
 
-                if (ipv6Match.getIpv6NdTll() != null) {
-                    MacAddress ipv6NdSll = ipv6Match.getIpv6NdTll();
+                if (sctpMatch.getSctpDestinationPort() != null) {
                     MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
                     matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-                    matchEntryBuilder.setOxmMatchField(Ipv6NdTll.class);
+                    matchEntryBuilder.setOxmMatchField(SctpDst.class);
 
-                    Ipv6NdTllCaseBuilder ipv6NdTllCaseBuilder = new Ipv6NdTllCaseBuilder();
-                    Ipv6NdTllBuilder ipv6NdTllBuilder = new Ipv6NdTllBuilder();
-                    ipv6NdTllBuilder.setMacAddress(ipv6NdSll);
-                    ipv6NdTllCaseBuilder.setIpv6NdTll(ipv6NdTllBuilder.build());
-                    matchEntryBuilder.setMatchEntryValue(ipv6NdTllCaseBuilder.build());
+                    SctpDstCaseBuilder sctpDstCaseBuilder = new SctpDstCaseBuilder();
+                    SctpDstBuilder sctpDstBuilder = new SctpDstBuilder();
+                    sctpDstBuilder.setPort(sctpMatch.getSctpDestinationPort());
+                    sctpDstCaseBuilder.setSctpDst(sctpDstBuilder.build());
+                    matchEntryBuilder.setMatchEntryValue(sctpDstCaseBuilder.build());
                     matchEntryBuilder.setHasMask(false);
                     matchEntryList.add(matchEntryBuilder.build());
-
-                }
-
-                if (ipv6Match.getIpv6ExtHeader() != null) {
-                    matchEntryList.add(toOfIpv6ExtHeader(ipv6Match.getIpv6ExtHeader()));
                 }
             }
         }
+    }
 
-        ProtocolMatchFields protocolMatchFields = match.getProtocolMatchFields();
-        if (protocolMatchFields != null) {
-            if (protocolMatchFields.getMplsLabel() != null) {
-                matchEntryList.add(toOfMplsLabel(protocolMatchFields.getMplsLabel()));
-            }
 
-            if (protocolMatchFields.getMplsBos() != null) {
-                matchEntryList.add(toOfMplsBos(protocolMatchFields.getMplsBos()));
+    private static void ipMatch(final List<MatchEntry> matchEntryList, final IpMatch ipMatch) {
+        if (ipMatch != null) {
+            if (ipMatch.getIpDscp() != null) {
+                matchEntryList.add(toOfIpDscp(ipMatch.getIpDscp()));
             }
 
-            if (protocolMatchFields.getMplsTc() != null) {
-                matchEntryList.add(toOfMplsTc(protocolMatchFields.getMplsTc()));
+            if (ipMatch.getIpEcn() != null) {
+                matchEntryList.add(toOfIpEcn(ipMatch.getIpEcn()));
             }
 
-            if (protocolMatchFields.getPbb() != null) {
-                matchEntryList.add(toOfMplsPbb(protocolMatchFields.getPbb()));
+            if (ipMatch.getIpProtocol() != null) {
+                matchEntryList.add(toOfIpProto(ipMatch.getIpProtocol()));
             }
         }
+    }
 
-        org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Tunnel tunnel = match
-                .getTunnel();
-        if (tunnel != null) {
 
+    private static void vlanMatch(final List<MatchEntry> matchEntryList, final VlanMatch vlanMatch) {
+        if (vlanMatch != null) {
+            if (vlanMatch.getVlanId() != null) {
+                VlanId vlanId = vlanMatch.getVlanId();
+                MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                matchEntryBuilder.setOxmMatchField(VlanVid.class);
 
-            MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-            TunnelIdCaseBuilder tunnelIdCaseBuilder = new TunnelIdCaseBuilder();
-            TunnelIdBuilder tunnelIdBuilder = new TunnelIdBuilder();
-            boolean hasMask = false;
-            if (null != tunnel.getTunnelMask()) {
-                hasMask = true;
-                tunnelIdBuilder.setMask(ByteUtil.convertBigIntegerToNBytes(tunnel.getTunnelMask(), OFConstants.SIZE_OF_LONG_IN_BYTES));
+                VlanVidCaseBuilder vlanVidCaseBuilder = new VlanVidCaseBuilder();
+                VlanVidBuilder vlanVidBuilder = new VlanVidBuilder();
+                boolean setCfiBit = false;
+                Integer vidEntryValue = 0;
+                boolean hasmask = false;
+                if (Boolean.TRUE.equals(vlanId.isVlanIdPresent())) {
+                    setCfiBit = true;
+                    if (vlanId.getVlanId() != null) {
+                        vidEntryValue = vlanId.getVlanId().getValue();
+                    }
+                    hasmask = (vidEntryValue == 0);
+                    if (hasmask) {
+                        vlanVidBuilder.setMask(VLAN_VID_MASK);
+                    }
+                }
+
+                vlanVidBuilder.setCfiBit(setCfiBit);
+                vlanVidBuilder.setVlanVid(vidEntryValue);
+                vlanVidCaseBuilder.setVlanVid(vlanVidBuilder.build());
+                matchEntryBuilder.setMatchEntryValue(vlanVidCaseBuilder.build());
+                matchEntryBuilder.setHasMask(hasmask);
+                matchEntryList.add(matchEntryBuilder.build());
+            }
+
+            if (vlanMatch.getVlanPcp() != null) {
+                matchEntryList.add(toOfVlanPcp(vlanMatch.getVlanPcp()));
             }
-            tunnelIdBuilder.setTunnelId(ByteUtil.convertBigIntegerToNBytes(tunnel.getTunnelId(), OFConstants.SIZE_OF_LONG_IN_BYTES));
-            tunnelIdCaseBuilder.setTunnelId(tunnelIdBuilder.build());
-            matchEntryBuilder.setMatchEntryValue(tunnelIdCaseBuilder.build());
-            matchEntryBuilder.setHasMask(hasMask);
-            matchEntryBuilder.setOxmMatchField(TunnelId.class);
-            matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-            matchEntryList.add(matchEntryBuilder.build());
         }
+    }
 
 
-        /**
-         * TODO: EXTENSION PROPOSAL (match, MD-SAL to OFJava)
-         * - we might need version for conversion and for key
-         * - sanitize NPE
-         */
-        Optional<GeneralExtensionListGrouping> extensionListOpt = ExtensionResolvers.getMatchExtensionResolver().getExtension(match);
-        if (extensionListOpt.isPresent()) {
-            for (ExtensionList extensionItem : extensionListOpt.get().getExtensionList()) {
-                // TODO: get real version
-                ConverterExtensionKey<? extends ExtensionKey> key = new ConverterExtensionKey<>(extensionItem.getExtensionKey(), OFConstants.OFP_VERSION_1_3);
-                ConvertorToOFJava<MatchEntry> convertor =
-                        OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
-                MatchEntry ofMatch = convertor.convert(extensionItem.getExtension());
-                matchEntryList.add(ofMatch);
+    private static void ethernetMatch(final List<MatchEntry> matchEntryList, final EthernetMatch ethernetMatch) {
+        if (ethernetMatch != null) {
+            EthernetDestination ethernetDestination = ethernetMatch.getEthernetDestination();
+            if (ethernetDestination != null) {
+                MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                matchEntryBuilder.setOxmMatchField(EthDst.class);
+                EthDstCaseBuilder ethDstCaseBuilder = new EthDstCaseBuilder();
+                EthDstBuilder ethDstBuilder = new EthDstBuilder();
+                ethDstBuilder.setMacAddress(ethernetDestination.getAddress());
+                boolean hasMask = false;
+                if (null != ethernetDestination.getMask()) {
+                    ethDstBuilder.setMask(ByteBufUtils.macAddressToBytes(ethernetDestination.getMask().getValue()));
+                    hasMask = true;
+                }
+                ethDstCaseBuilder.setEthDst(ethDstBuilder.build());
+                matchEntryBuilder.setMatchEntryValue(ethDstCaseBuilder.build());
+                matchEntryBuilder.setHasMask(hasMask);
+                matchEntryList.add(matchEntryBuilder.build());
             }
-        }
 
-        return matchEntryList;
+            EthernetSource ethernetSource = ethernetMatch.getEthernetSource();
+            if (ethernetSource != null) {
+                MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
+                matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
+                matchEntryBuilder.setOxmMatchField(EthSrc.class);
+
+                EthSrcCaseBuilder ethSrcCaseBuilder = new EthSrcCaseBuilder();
+                EthSrcBuilder ethDstBuilder = new EthSrcBuilder();
+                ethDstBuilder.setMacAddress(ethernetSource.getAddress());
+                boolean hasMask = false;
+                if (null != ethernetSource.getMask()) {
+                    ethDstBuilder.setMask(ByteBufUtils.macAddressToBytes(ethernetSource.getMask().getValue()));
+                    hasMask = true;
+                }
+                ethSrcCaseBuilder.setEthSrc(ethDstBuilder.build());
+                matchEntryBuilder.setMatchEntryValue(ethSrcCaseBuilder.build());
+                matchEntryBuilder.setHasMask(hasMask);
+                matchEntryList.add(matchEntryBuilder.build());
+            }
+
+            if (ethernetMatch.getEthernetType() != null) {
+                matchEntryList.add(toOfEthernetType(ethernetMatch.getEthernetType()));
+            }
+        }
     }
 
 
-    private static byte[] extractIpv4Mask(boolean hasMask, final Iterator<String> addressParts) {
+    private static byte[] extractIpv4Mask(final Iterator<String> addressParts) {
         final int prefix;
         if (addressParts.hasNext()) {
             int potentionalPrefix = Integer.parseInt(addressParts.next());
@@ -869,11 +950,8 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         }
 
         if (prefix != 0) {
-            int mask = 0xffffffff << (32 - prefix);
-            byte[] maskBytes = new byte[]{(byte) (mask >>> 24), (byte) (mask >>> 16), (byte) (mask >>> 8),
-                    (byte) mask};
-            hasMask = true;
-            return maskBytes;
+            // clone() is necessary to protect our constants
+            return IPV4_MASKS[prefix].clone();
         }
         return null;
     }
@@ -881,12 +959,12 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
     /**
      * Method convert Openflow 1.0 specific flow match to MD-SAL format flow
      * match
-     *
-     * @param swMatch
-     * @return
-     * @author avishnoi@in.ibm.com
+     * @param swMatch source match
+     * @param datapathid datapath id
+     * @param ofVersion openflow version
+     * @return match builder
      */
-    public static Match fromOFMatchV10ToSALMatch(final MatchV10 swMatch, final BigInteger datapathid, final OpenflowVersion ofVersion) {
+    public static MatchBuilder fromOFMatchV10ToSALMatch(@Nonnull final MatchV10 swMatch, @Nonnull final BigInteger datapathid, @Nonnull final OpenflowVersion ofVersion) {
         MatchBuilder matchBuilder = new MatchBuilder();
         EthernetMatchBuilder ethMatchBuilder = new EthernetMatchBuilder();
         VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
@@ -930,36 +1008,34 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
             matchBuilder.setVlanMatch(vlanMatchBuilder.build());
         }
         if (!swMatch.getWildcards().isDLTYPE().booleanValue() && swMatch.getNwSrc() != null) {
-            String ipv4PrefixStr = swMatch.getNwSrc().getValue();
+            final Ipv4Prefix prefix;
             if (swMatch.getNwSrcMask() != null) {
-                ipv4PrefixStr += IpConversionUtil.PREFIX_SEPARATOR + swMatch.getNwSrcMask();
+                prefix = IetfInetUtil.INSTANCE.ipv4PrefixFor(swMatch.getNwSrc(), swMatch.getNwSrcMask());
             } else {
                 //Openflow Spec : 1.3.2
                 //An all-one-bits oxm_mask is equivalent to specifying 0 for oxm_hasmask and omitting oxm_mask.
                 // So when user specify 32 as a mast, switch omit that mast and we get null as a mask in flow
                 // statistics response.
-
-                ipv4PrefixStr += IpConversionUtil.PREFIX_SEPARATOR + "32";
+                prefix = IetfInetUtil.INSTANCE.ipv4PrefixFor(swMatch.getNwSrc());
             }
-            if (!noIp.equals(ipv4PrefixStr)) {
-                ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(ipv4PrefixStr));
+            if (!NO_IP.equals(prefix.getValue())) {
+                ipv4MatchBuilder.setIpv4Source(prefix);
                 matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
             }
         }
         if (!swMatch.getWildcards().isDLTYPE().booleanValue() && swMatch.getNwDst() != null) {
-            String ipv4PrefixStr = swMatch.getNwDst().getValue();
+            final Ipv4Prefix prefix;
             if (swMatch.getNwDstMask() != null) {
-                ipv4PrefixStr += IpConversionUtil.PREFIX_SEPARATOR + swMatch.getNwDstMask();
+                prefix = IetfInetUtil.INSTANCE.ipv4PrefixFor(swMatch.getNwDst(), swMatch.getNwDstMask());
             } else {
                 //Openflow Spec : 1.3.2
                 //An all-one-bits oxm_mask is equivalent to specifying 0 for oxm_hasmask and omitting oxm_mask.
                 // So when user specify 32 as a mast, switch omit that mast and we get null as a mask in flow
                 // statistics response.
-
-                ipv4PrefixStr += IpConversionUtil.PREFIX_SEPARATOR + "32";
+                prefix = IetfInetUtil.INSTANCE.ipv4PrefixFor(swMatch.getNwDst());
             }
-            if (!noIp.equals(ipv4PrefixStr)) {
-                ipv4MatchBuilder.setIpv4Destination(new Ipv4Prefix(ipv4PrefixStr));
+            if (!NO_IP.equals(prefix.getValue())) {
+                ipv4MatchBuilder.setIpv4Destination(prefix);
                 matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
             }
         }
@@ -1036,23 +1112,22 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
             matchBuilder.setIpMatch(ipMatchBuilder.build());
         }
 
-        return matchBuilder.build();
+        return matchBuilder;
     }
 
     /**
      * Method converts Openflow 1.3+ specific flow match to MD-SAL format flow
      * match
      *
-     * @param swMatch
-     * @param swMatch
-     * @param datapathid
-     * @param ofVersion
+     * @param swMatch source match
+     * @param datapathid datapath id
+     * @param ofVersion openflow version
      * @return md-sal match instance
      * @author avishnoi@in.ibm.com
      */
     public static MatchBuilder fromOFMatchToSALMatch(
-            final org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match swMatch,
-            final BigInteger datapathid, final OpenflowVersion ofVersion) {
+            @Nonnull final org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match swMatch,
+            @Nonnull final BigInteger datapathid, @Nonnull final OpenflowVersion ofVersion) {
         return OfMatchToSALMatchConvertor(swMatch.getMatchEntry(), datapathid, ofVersion);
     }
 
@@ -1069,10 +1144,10 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         Icmpv4MatchBuilder icmpv4MatchBuilder = new Icmpv4MatchBuilder();
         Icmpv6MatchBuilder icmpv6MatchBuilder = new Icmpv6MatchBuilder();
         Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder();
+        Ipv4MatchArbitraryBitMaskBuilder ipv4MatchArbitraryBitMaskBuilder = new Ipv4MatchArbitraryBitMaskBuilder();
         ArpMatchBuilder arpMatchBuilder = new ArpMatchBuilder();
         Ipv6MatchBuilder ipv6MatchBuilder = new Ipv6MatchBuilder();
         ProtocolMatchFieldsBuilder protocolMatchFieldsBuilder = new ProtocolMatchFieldsBuilder();
-        TcpFlagMatchBuilder tcpFlagMatchBuilder = new TcpFlagMatchBuilder();
         TunnelIpv4MatchBuilder tunnelIpv4MatchBuilder = new TunnelIpv4MatchBuilder();
 
         for (MatchEntry ofMatch : swMatchList) {
@@ -1241,17 +1316,33 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ipv4.src._case.Ipv4Src ipv4Address = ((Ipv4SrcCase) ofMatch.getMatchEntryValue()).getIpv4Src();
                 if (ipv4Address != null) {
                     byte[] mask = ipv4Address.getMask();
-                    String ipv4PrefixStr = ipv4Address.getIpv4Address().getValue();
-                    setIpv4MatchBuilderFields(ipv4MatchBuilder, ofMatch, mask, ipv4PrefixStr);
-                    matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+                    if (mask != null && IpConversionUtil.isArbitraryBitMask(mask)) {
+                        DottedQuad dottedQuadMask = IpConversionUtil.createArbitraryBitMask(mask);
+                        String Ipv4Address = ipv4Address.getIpv4Address().getValue();
+                        setIpv4MatchArbitraryBitMaskBuilderFields(ipv4MatchArbitraryBitMaskBuilder, ofMatch, dottedQuadMask, Ipv4Address);
+                        matchBuilder.setLayer3Match(ipv4MatchArbitraryBitMaskBuilder.build());
+                    }
+                    else {
+                        String ipv4PrefixStr = ipv4Address.getIpv4Address().getValue();
+                        setIpv4MatchBuilderFields(ipv4MatchBuilder, ofMatch, mask, ipv4PrefixStr);
+                        matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+                    }
                 }
             } else if (ofMatch.getOxmMatchField().equals(Ipv4Dst.class)) {
                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ipv4.dst._case.Ipv4Dst ipv4Address = ((Ipv4DstCase) ofMatch.getMatchEntryValue()).getIpv4Dst();
                 if (ipv4Address != null) {
                     byte[] mask = ipv4Address.getMask();
-                    String ipv4PrefixStr = ipv4Address.getIpv4Address().getValue();
-                    setIpv4MatchBuilderFields(ipv4MatchBuilder, ofMatch, mask, ipv4PrefixStr);
-                    matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+                    if(mask != null && IpConversionUtil.isArbitraryBitMask(mask)) {
+                        DottedQuad dottedQuadMask = IpConversionUtil.createArbitraryBitMask(mask);
+                        String Ipv4Address = ipv4Address.getIpv4Address().getValue();
+                        setIpv4MatchArbitraryBitMaskBuilderFields(ipv4MatchArbitraryBitMaskBuilder, ofMatch, dottedQuadMask, Ipv4Address);
+                        matchBuilder.setLayer3Match(ipv4MatchArbitraryBitMaskBuilder.build());
+                    }
+                    else {
+                        String ipv4PrefixStr = ipv4Address.getIpv4Address().getValue();
+                        setIpv4MatchBuilderFields(ipv4MatchBuilder, ofMatch, mask, ipv4PrefixStr);
+                        matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
+                    }
                 }
             } else if (ofMatch.getOxmMatchField().equals(TunnelIpv4Dst.class)
                     || ofMatch.getOxmMatchField().equals(TunnelIpv4Src.class)) {
@@ -1463,7 +1554,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
     }
 
     private static void setIpv4MatchBuilderFields(final Ipv4MatchBuilder ipv4MatchBuilder, final MatchEntry ofMatch, final byte[] mask, final String ipv4PrefixStr) {
-        Ipv4Prefix ipv4Prefix;
+        final Ipv4Prefix ipv4Prefix;
         if (mask != null) {
             ipv4Prefix = IpConversionUtil.createPrefix(new Ipv4Address(ipv4PrefixStr), mask);
         } else {
@@ -1481,6 +1572,27 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         }
     }
 
+    private static void setIpv4MatchArbitraryBitMaskBuilderFields(final Ipv4MatchArbitraryBitMaskBuilder ipv4MatchArbitraryBitMaskBuilder, final MatchEntry ofMatch, final DottedQuad mask, final String ipv4AddressStr) {
+        Ipv4Address ipv4Address;
+        DottedQuad dottedQuad;
+        if (mask != null) {
+            dottedQuad = mask;
+            if (ofMatch.getOxmMatchField().equals(Ipv4Src.class)) {
+                ipv4MatchArbitraryBitMaskBuilder.setIpv4SourceArbitraryBitmask(dottedQuad);
+            }
+            if (ofMatch.getOxmMatchField().equals(Ipv4Dst.class)) {
+                ipv4MatchArbitraryBitMaskBuilder.setIpv4DestinationArbitraryBitmask(dottedQuad);
+            }
+        }
+        ipv4Address = new Ipv4Address(ipv4AddressStr);
+        if (ofMatch.getOxmMatchField().equals(Ipv4Src.class)) {
+            ipv4MatchArbitraryBitMaskBuilder.setIpv4SourceAddressNoMask(ipv4Address);
+        }
+        if (ofMatch.getOxmMatchField().equals(Ipv4Dst.class)) {
+            ipv4MatchArbitraryBitMaskBuilder.setIpv4DestinationAddressNoMask(ipv4Address);
+        }
+    }
+
 
     private static MatchEntry toOfMplsPbb(final Pbb pbb) {
         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
@@ -1524,7 +1636,7 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         if (mplsBos.shortValue() != 0) {
             isBos = true;
         }
-        mplsBosBuilder.setBos(new Boolean(isBos));
+        mplsBosBuilder.setBos(isBos);
         mplsBosCaseBuilder.setMplsBos(mplsBosBuilder.build());
 
         matchEntryBuilder.setMatchEntryValue(mplsBosCaseBuilder.build());
@@ -1735,33 +1847,6 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         return matchEntryBuilder.build();
     }
 
-    private static MatchEntry toOfVlanVid(final VlanId vlanId) {
-        // TODO: verify
-        boolean hasmask = false;
-        boolean setCfiBit = false;
-        Integer vidEntryValue = 0;
-        MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
-        matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
-        matchEntryBuilder.setOxmMatchField(VlanVid.class);
-        VlanVidCaseBuilder vlanVidCaseBuilder = new VlanVidCaseBuilder();
-        VlanVidBuilder vlanVidBuilder = new VlanVidBuilder();
-        if (Boolean.TRUE.equals(vlanId.isVlanIdPresent())) {
-            setCfiBit = true;
-            if (vlanId.getVlanId() != null) {
-                vidEntryValue = vlanId.getVlanId().getValue();
-            }
-            hasmask = (vidEntryValue == 0);
-        }
-        vlanVidBuilder.setCfiBit(setCfiBit);
-        vlanVidBuilder.setVlanVid(vidEntryValue);
-        if (hasmask) {
-            vlanVidBuilder.setMask(VLAN_VID_MASK);
-        }
-        vlanVidCaseBuilder.setVlanVid(vlanVidBuilder.build());
-        matchEntryBuilder.setMatchEntryValue(vlanVidCaseBuilder.build());
-        matchEntryBuilder.setHasMask(hasmask);
-        return matchEntryBuilder.build();
-    }
 
     private static MatchEntry toOfIpProto(final Short ipProtocol) {
         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
@@ -1817,29 +1902,14 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
     }
 
 
-//    /**
-//     * Method converts OF SetField action to SAL SetFiled action.
-//     *
-//     * @param action
-//     * @param ofVersion current ofp version
-//     * @return
-//     */
-//    public static SetField fromOFSetFieldToSALSetFieldAction(
-//            final Action action, OpenflowVersion ofVersion) {
-//        logger.debug("Converting OF SetField action to SAL SetField action");
-//        SetFieldBuilder setField = new SetFieldBuilder();
-//        OxmFieldsAction oxmFields = action.getAugmentation(OxmFieldsAction.class);
-//        MatchBuilder match = OfMatchToSALMatchConvertor(oxmFields.getMatchEntry(), null, ofVersion);
-//        setField.fieldsFrom(match.build());
-//        return setField.build();
-//    }
+
 
     /**
      * Method converts OF SetField action to SAL SetFiled action.
      *
-     * @param action
+     * @param action input action
      * @param ofVersion current ofp version
-     * @return
+     * @return set field builder
      */
     public static SetField fromOFSetFieldToSALSetFieldAction(
             final Action action, final OpenflowVersion ofVersion) {
@@ -1853,5 +1923,4 @@ public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
         return setField.build();
     }
 
-
 }