Bug 2756 - Match model update
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / util / MatchDeserializer.java
index 98b01c4b0745b39ed4295519876f19a71c28172c..0a6852defe69f9a7977c7470f4c02d402821588e 100644 (file)
-/* Copyright (C)2013 Pantheon Technologies, s.r.o. All rights reserved. */\r
-package org.opendaylight.openflowjava.protocol.impl.util;\r
-\r
-import io.netty.buffer.ByteBuf;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6FlowLabel;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.BosMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.BosMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.DscpMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.DscpMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EcnMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EcnMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthTypeMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthTypeMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4CodeMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4CodeMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4TypeMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4TypeMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6CodeMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6CodeMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6TypeMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6TypeMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv4AddressMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv4AddressMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv6AddressMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv6AddressMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv6FlabelMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv6FlabelMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.IsidMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.IsidMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MacAddressMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MacAddressMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaskMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaskMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsLabelMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsLabelMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OpCodeMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OpCodeMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ProtocolNumberMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ProtocolNumberMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PseudoFieldMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PseudoFieldMatchEntry.PseudoField;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PseudoFieldMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TcMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TcMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanPcpMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanPcpMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanVidMatchEntry;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanVidMatchEntryBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.StandardMatchType;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpOp;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpSha;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpSpa;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpTha;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpTpa;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthDst;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthSrc;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthType;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ExperimenterClass;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv4Code;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv4Type;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv6Code;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv6Type;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPhyPort;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPort;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpDscp;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpEcn;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpProto;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv4Dst;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv4Src;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Dst;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Exthdr;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Flabel;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdSll;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdTarget;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdTll;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Src;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Metadata;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsBos;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsLabel;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsTc;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Nxm0Class;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Nxm1Class;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OpenflowBasicClass;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OxmMatchType;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.PbbIsid;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.SctpDst;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.SctpSrc;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TcpDst;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TcpSrc;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TunnelId;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.UdpDst;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.UdpSrc;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.VlanPcp;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.VlanVid;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntriesBuilder;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.match.grouping.Match;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.match.grouping.MatchBuilder;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import com.google.common.base.Joiner;\r
-\r
-/**\r
- * Deserializes ofp_match (OpenFlow v1.3) and its oxm_fields structures\r
- * @author timotej.kubas\r
- * @author michal.polkorab\r
- */\r
-public abstract class MatchDeserializer {\r
-    private static final Logger LOGGER = LoggerFactory.getLogger(MatchDeserializer.class);\r
-    private static final byte SIZE_OF_LONG_IN_BYTES = Long.SIZE / Byte.SIZE;\r
-    private static final byte SIZE_OF_INT_IN_BYTES = Integer.SIZE / Byte.SIZE;\r
-    private static final byte SIZE_OF_SHORT_IN_BYTES = Short.SIZE / Byte.SIZE;\r
-    private static final byte SIZE_OF_BYTE_IN_BYTES = Byte.SIZE / Byte.SIZE;\r
-    private static final byte SIZE_OF_IPV6_ADDRESS_IN_BYTES = (8 * Short.SIZE) / Byte.SIZE;\r
-    \r
-    \r
-    /**\r
-     * Creates match\r
-     * @param in input ByteBuf\r
-     * @return ofp_match (OpenFlow v1.3)\r
-     */\r
-    public static Match createMatch(ByteBuf in) {\r
-        if (in.readableBytes() > 0) {\r
-            MatchBuilder builder = new MatchBuilder();\r
-            int type = in.readUnsignedShort();\r
-            int length = in.readUnsignedShort();\r
-            switch (type) {\r
-            case 0:\r
-                builder.setType(StandardMatchType.class);\r
-                break;\r
-            case 1:\r
-                builder.setType(OxmMatchType.class);\r
-                break;\r
-            default:\r
-                break;\r
-            }\r
-            builder.setMatchEntries(createMatchEntries(in, length - 2 * (Short.SIZE / Byte.SIZE)));\r
-            int paddingRemainder = length % EncodeConstants.PADDING;\r
-            if (paddingRemainder != 0) {\r
-                in.skipBytes(EncodeConstants.PADDING - paddingRemainder);\r
-            }\r
-            return builder.build();\r
-        }\r
-        return null;\r
-    }\r
-    \r
-    /**\r
-     * Deserializes single match entry (oxm_field)\r
-     * @param in input ByteBuf\r
-     * @param matchLength length of match entry\r
-     * @return MatchEntriesList list containing one match entry\r
-     */\r
-    public static List<MatchEntries> createMatchEntry(ByteBuf in, int matchLength) {\r
-        return createMatchEntriesInternal(in, matchLength, true);\r
-    }\r
-    \r
-    /**\r
-     * @param in input ByteBuf\r
-     * @param matchLength length of match entries\r
-     * @return MatchEntriesList list of match entries\r
-     */\r
-    public static List<MatchEntries> createMatchEntries(ByteBuf in, int matchLength) {\r
-        return createMatchEntriesInternal(in, matchLength, false);\r
-    }\r
-    \r
-    private static List<MatchEntries> createMatchEntriesInternal(ByteBuf in, int matchLength, boolean oneEntry) {\r
-        List<MatchEntries> matchEntriesList = new ArrayList<>();\r
-        int currLength = 0;\r
-        while(currLength < matchLength) {\r
-            MatchEntriesBuilder matchEntriesBuilder = new MatchEntriesBuilder(); \r
-            switch (in.readUnsignedShort()) { \r
-            case 0x0000:\r
-                        matchEntriesBuilder.setOxmClass(Nxm0Class.class);\r
-                        break;\r
-            case 0x0001:\r
-                        matchEntriesBuilder.setOxmClass(Nxm1Class.class);\r
-                        break;\r
-            case 0x8000:\r
-                        matchEntriesBuilder.setOxmClass(OpenflowBasicClass.class);\r
-                        break;\r
-            case 0xFFFF:\r
-                        matchEntriesBuilder.setOxmClass(ExperimenterClass.class);\r
-                        break;\r
-            default:\r
-                        break;\r
-            }\r
-\r
-            int fieldAndMask = in.readUnsignedByte();\r
-            boolean hasMask = (fieldAndMask & 1) != 0;\r
-            int matchField =  fieldAndMask >> 1;\r
-            int matchEntryLength = in.readUnsignedByte();\r
-            currLength += SIZE_OF_SHORT_IN_BYTES + (2 * SIZE_OF_BYTE_IN_BYTES) + matchEntryLength;\r
-            \r
-            switch(matchField) {\r
-            case 0: \r
-                matchEntriesBuilder.setOxmMatchField(InPort.class);\r
-                PortNumberMatchEntryBuilder port = new PortNumberMatchEntryBuilder();\r
-                port.setPortNumber(new PortNumber(in.readUnsignedInt())); \r
-                matchEntriesBuilder.addAugmentation(PortNumberMatchEntry.class, port.build());\r
-                break;\r
-            case 1:\r
-                matchEntriesBuilder.setOxmMatchField(InPhyPort.class);\r
-                PortNumberMatchEntryBuilder phyPort = new PortNumberMatchEntryBuilder();\r
-                phyPort.setPortNumber(new PortNumber(in.readUnsignedInt())); \r
-                matchEntriesBuilder.addAugmentation(PortNumberMatchEntry.class, phyPort.build());\r
-                break;\r
-            case 2:\r
-                matchEntriesBuilder.setOxmMatchField(Metadata.class);\r
-                addMetadataAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_LONG_IN_BYTES);\r
-                }\r
-                break;\r
-            case 3:\r
-                matchEntriesBuilder.setOxmMatchField(EthDst.class);\r
-                addMacAddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_LONG_IN_BYTES);\r
-                }\r
-                break;\r
-            case 4:\r
-                matchEntriesBuilder.setOxmMatchField(EthSrc.class);\r
-                addMacAddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_LONG_IN_BYTES);\r
-                }\r
-                break;\r
-            case 5:\r
-                matchEntriesBuilder.setOxmMatchField(EthType.class);\r
-                EthTypeMatchEntryBuilder ethertypeBuilder = new EthTypeMatchEntryBuilder();\r
-                ethertypeBuilder.setEthType(new EtherType(in.readUnsignedShort()));\r
-                matchEntriesBuilder.addAugmentation(EthTypeMatchEntry.class, ethertypeBuilder.build());\r
-                break;\r
-            case 6:\r
-                matchEntriesBuilder.setOxmMatchField(VlanVid.class);\r
-                VlanVidMatchEntryBuilder vlanVidBuilder = new VlanVidMatchEntryBuilder();\r
-                int vidEntryValue = in.readUnsignedShort(); \r
-                vlanVidBuilder.setCfiBit((vidEntryValue & 1) != 0);\r
-                vlanVidBuilder.setVlanVid(vidEntryValue >> 1);\r
-                matchEntriesBuilder.addAugmentation(VlanVidMatchEntry.class, vlanVidBuilder.build());\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_SHORT_IN_BYTES);\r
-                }\r
-                break;\r
-            case 7:\r
-                matchEntriesBuilder.setOxmMatchField(VlanPcp.class);\r
-                VlanPcpMatchEntryBuilder vlanPcpBuilder = new VlanPcpMatchEntryBuilder();\r
-                vlanPcpBuilder.setVlanPcp(in.readUnsignedByte());\r
-                matchEntriesBuilder.addAugmentation(VlanPcpMatchEntry.class, vlanPcpBuilder.build());\r
-                break;\r
-            case 8:\r
-                matchEntriesBuilder.setOxmMatchField(IpDscp.class);\r
-                DscpMatchEntryBuilder dscpBuilder = new DscpMatchEntryBuilder();\r
-                dscpBuilder.setDscp(new Dscp(in.readUnsignedByte()));\r
-                matchEntriesBuilder.addAugmentation(DscpMatchEntry.class, dscpBuilder.build());\r
-                break;\r
-            case 9:\r
-                matchEntriesBuilder.setOxmMatchField(IpEcn.class);\r
-                EcnMatchEntryBuilder ecnBuilder = new EcnMatchEntryBuilder();\r
-                ecnBuilder.setEcn(in.readUnsignedByte());\r
-                matchEntriesBuilder.addAugmentation(EcnMatchEntry.class, ecnBuilder.build());\r
-                break;\r
-            case 10:\r
-                matchEntriesBuilder.setOxmMatchField(IpProto.class);\r
-                ProtocolNumberMatchEntryBuilder protoNumberBuilder = new ProtocolNumberMatchEntryBuilder();\r
-                protoNumberBuilder.setProtocolNumber(in.readUnsignedByte());\r
-                matchEntriesBuilder.addAugmentation(ProtocolNumberMatchEntry.class, protoNumberBuilder.build());\r
-                break;\r
-            case 11:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv4Src.class);\r
-                // TODO - ipv4address - check format with tests\r
-                LOGGER.warn("IPV4address(ipv4src): received but possible wrong deserialization");\r
-                addIpv4AddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_INT_IN_BYTES);\r
-                }\r
-                break;\r
-            case 12:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv4Dst.class);\r
-                // TODO - ipv4address - check format with tests\r
-                LOGGER.warn("IPV4address(ipv4dst): received but possible wrong deserialization");\r
-                addIpv4AddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_INT_IN_BYTES);\r
-                }\r
-                break;\r
-            case 13:\r
-                matchEntriesBuilder.setOxmMatchField(TcpSrc.class);\r
-                addPortAugmentation(null, in);\r
-                break;\r
-            case 14:\r
-                matchEntriesBuilder.setOxmMatchField(TcpDst.class);\r
-                addPortAugmentation(null, in);\r
-                break;\r
-            case 15:\r
-                matchEntriesBuilder.setOxmMatchField(UdpSrc.class);\r
-                addPortAugmentation(null, in);\r
-                break;\r
-            case 16:\r
-                matchEntriesBuilder.setOxmMatchField(UdpDst.class);\r
-                addPortAugmentation(null, in);\r
-                break;\r
-            case 17:\r
-                matchEntriesBuilder.setOxmMatchField(SctpSrc.class);\r
-                addPortAugmentation(null, in);\r
-                break;\r
-            case 18:\r
-                matchEntriesBuilder.setOxmMatchField(SctpDst.class);\r
-                addPortAugmentation(null, in);\r
-                break;\r
-            case 19:\r
-                matchEntriesBuilder.setOxmMatchField(Icmpv4Type.class);\r
-                Icmpv4TypeMatchEntryBuilder icmpv4TypeBuilder = new Icmpv4TypeMatchEntryBuilder();\r
-                icmpv4TypeBuilder.setIcmpv4Type(in.readUnsignedByte());\r
-                matchEntriesBuilder.addAugmentation(Icmpv4TypeMatchEntry.class, icmpv4TypeBuilder.build());\r
-                break;\r
-            case 20:\r
-                matchEntriesBuilder.setOxmMatchField(Icmpv4Code.class);\r
-                Icmpv4CodeMatchEntryBuilder icmpv4CodeBuilder = new Icmpv4CodeMatchEntryBuilder();\r
-                icmpv4CodeBuilder.setIcmpv4Code(in.readUnsignedByte());\r
-                matchEntriesBuilder.addAugmentation(Icmpv4CodeMatchEntry.class, icmpv4CodeBuilder.build());\r
-                break;\r
-            case 21:\r
-                matchEntriesBuilder.setOxmMatchField(ArpOp.class);\r
-                OpCodeMatchEntryBuilder opcodeBuilder = new OpCodeMatchEntryBuilder();\r
-                opcodeBuilder.setOpCode(in.readUnsignedShort());\r
-                matchEntriesBuilder.addAugmentation(OpCodeMatchEntry.class, opcodeBuilder.build());\r
-                break;\r
-            case 22:\r
-                matchEntriesBuilder.setOxmMatchField(ArpSpa.class);\r
-                // TODO - ipv4address - check format with tests\r
-                LOGGER.warn("IPV4address(arpspa): received but possible wrong deserialization");\r
-                addIpv4AddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_INT_IN_BYTES);\r
-                }\r
-                break;\r
-            case 23:\r
-                matchEntriesBuilder.setOxmMatchField(ArpTpa.class);\r
-                // TODO - ipv4address - check format with tests\r
-                LOGGER.warn("IPV4address(arptpa): received but possible wrong deserialization");\r
-                addIpv4AddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_INT_IN_BYTES);\r
-                }\r
-                break;\r
-            case 24:\r
-                matchEntriesBuilder.setOxmMatchField(ArpSha.class);\r
-                addMacAddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_LONG_IN_BYTES);\r
-                }\r
-                break;\r
-            case 25:\r
-                matchEntriesBuilder.setOxmMatchField(ArpTha.class);\r
-                addMacAddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_LONG_IN_BYTES);\r
-                }\r
-                break;\r
-            case 26:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv6Src.class);\r
-                // TODO - ipv6address - check format with tests\r
-                LOGGER.warn("IPV6address(Ipv6Src): received but possible wrong deserialization");\r
-                addIpv6AddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_IPV6_ADDRESS_IN_BYTES);\r
-                }\r
-                break;\r
-            case 27:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv6Dst.class);\r
-                // TODO - ipv6address - check format with tests\r
-                LOGGER.warn("IPV6address(Ipv6Dst): received but possible wrong deserialization");\r
-                addIpv6AddressAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_IPV6_ADDRESS_IN_BYTES);\r
-                }\r
-                break;\r
-            case 28:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv6Flabel.class);\r
-                Ipv6FlabelMatchEntryBuilder ipv6FlabelBuilder = new Ipv6FlabelMatchEntryBuilder();\r
-                ipv6FlabelBuilder.setIpv6Flabel(new Ipv6FlowLabel(in.readUnsignedInt()));\r
-                matchEntriesBuilder.addAugmentation(Ipv6FlabelMatchEntry.class, ipv6FlabelBuilder.build());\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_INT_IN_BYTES);\r
-                }\r
-                break;\r
-            case 29:\r
-                matchEntriesBuilder.setOxmMatchField(Icmpv6Type.class);\r
-                Icmpv6TypeMatchEntryBuilder icmpv6TypeBuilder = new Icmpv6TypeMatchEntryBuilder();\r
-                icmpv6TypeBuilder.setIcmpv6Type(in.readUnsignedByte());\r
-                matchEntriesBuilder.addAugmentation(Icmpv6TypeMatchEntry.class, icmpv6TypeBuilder.build());\r
-                break;\r
-            case 30:\r
-                matchEntriesBuilder.setOxmMatchField(Icmpv6Code.class);\r
-                Icmpv6CodeMatchEntryBuilder icmpv6CodeBuilder = new Icmpv6CodeMatchEntryBuilder();\r
-                icmpv6CodeBuilder.setIcmpv6Code(in.readUnsignedByte());\r
-                matchEntriesBuilder.addAugmentation(Icmpv6CodeMatchEntry.class, icmpv6CodeBuilder.build());\r
-                break;\r
-            case 31:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv6NdTarget.class);\r
-                // TODO - ipv6address - check format with tests\r
-                LOGGER.warn("IPV6address(Ipv6NdTarget): received but possible wrong deserialization");\r
-                addIpv6AddressAugmentation(matchEntriesBuilder, in);\r
-                break;\r
-            case 32:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv6NdSll.class);\r
-                addMacAddressAugmentation(matchEntriesBuilder, in);\r
-                break;\r
-            case 33:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv6NdTll.class);\r
-                addMacAddressAugmentation(matchEntriesBuilder, in);\r
-                break;\r
-            case 34:\r
-                matchEntriesBuilder.setOxmMatchField(MplsLabel.class);\r
-                MplsLabelMatchEntryBuilder mplsLabelBuilder = new MplsLabelMatchEntryBuilder();\r
-                mplsLabelBuilder.setMplsLabel(in.readUnsignedInt());\r
-                matchEntriesBuilder.addAugmentation(MplsLabelMatchEntry.class, mplsLabelBuilder.build());\r
-                break;\r
-            case 35:\r
-                matchEntriesBuilder.setOxmMatchField(MplsTc.class);\r
-                TcMatchEntryBuilder tcBuilder = new TcMatchEntryBuilder();\r
-                tcBuilder.setTc(in.readUnsignedByte());\r
-                matchEntriesBuilder.addAugmentation(TcMatchEntry.class, tcBuilder.build());\r
-                break;\r
-            case 36:\r
-                matchEntriesBuilder.setOxmMatchField(MplsBos.class);\r
-                BosMatchEntryBuilder bosBuilder = new BosMatchEntryBuilder();\r
-                if (in.readUnsignedByte() != 0) {\r
-                    bosBuilder.setBos(true);\r
-                } else {\r
-                    bosBuilder.setBos(false);\r
-                }\r
-                matchEntriesBuilder.addAugmentation(BosMatchEntry.class, bosBuilder.build());\r
-                break;\r
-            case 37:\r
-                matchEntriesBuilder.setOxmMatchField(PbbIsid.class);\r
-                IsidMatchEntryBuilder isidBuilder = new IsidMatchEntryBuilder();\r
-                isidBuilder.setIsid(in.readUnsignedInt());\r
-                matchEntriesBuilder.addAugmentation(IsidMatchEntry.class, isidBuilder.build());\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_INT_IN_BYTES);\r
-                }\r
-                break;\r
-            case 38:\r
-                matchEntriesBuilder.setOxmMatchField(TunnelId.class);\r
-                addMetadataAugmentation(matchEntriesBuilder, in);\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_LONG_IN_BYTES);\r
-                }\r
-                break;\r
-            case 39:\r
-                matchEntriesBuilder.setOxmMatchField(Ipv6Exthdr.class);\r
-                PseudoFieldMatchEntryBuilder pseudoBuilder = new PseudoFieldMatchEntryBuilder();\r
-                int bitmap = in.readUnsignedShort();\r
-                final Boolean NONEXT = ((bitmap) & (1<<0)) != 0;\r
-                final Boolean ESP = ((bitmap) & (1<<1)) != 0;\r
-                final Boolean AUTH = ((bitmap) & (1<<2)) != 0;\r
-                final Boolean DEST = ((bitmap) & (1<<3)) != 0;\r
-                final Boolean FRAG = ((bitmap) & (1<<4)) != 0;\r
-                final Boolean ROUTER = ((bitmap) & (1<<5)) != 0;\r
-                final Boolean HOP = ((bitmap) & (1<<6)) != 0;\r
-                final Boolean UNREP = ((bitmap) & (1<<7)) != 0;\r
-                final Boolean UNSEQ = ((bitmap) & (1<<8)) != 0;\r
-                pseudoBuilder.setPseudoField(new PseudoField(AUTH, DEST, ESP, FRAG, HOP, NONEXT, ROUTER, UNREP, UNSEQ));\r
-                matchEntriesBuilder.addAugmentation(PseudoFieldMatchEntry.class, pseudoBuilder.build());\r
-                if (hasMask) {\r
-                    addMaskAugmentation(matchEntriesBuilder, in, SIZE_OF_SHORT_IN_BYTES);\r
-                }\r
-                break;\r
-            default: \r
-                break;\r
-            }\r
-          matchEntriesList.add(matchEntriesBuilder.build());\r
-          if (oneEntry) {\r
-              break;\r
-          }\r
-        }\r
-        if ((matchLength - currLength) > 0) {\r
-            in.skipBytes(matchLength - currLength);\r
-        }\r
-        return matchEntriesList;\r
-    }\r
-\r
-    private static void addMaskAugmentation(MatchEntriesBuilder builder, ByteBuf in, int matchEntryLength) {\r
-        MaskMatchEntryBuilder maskBuilder = new MaskMatchEntryBuilder();\r
-        byte[] mask = new byte[matchEntryLength];\r
-        in.readBytes(mask);\r
-        maskBuilder.setMask(mask);\r
-        builder.addAugmentation(MaskMatchEntry.class, maskBuilder.build());\r
-    }\r
-\r
-    private static void addIpv6AddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) {\r
-        final byte GROUPS_IN_IPV6_ADDRESS = 8;\r
-        Ipv6AddressMatchEntryBuilder ipv6AddressBuilder = new Ipv6AddressMatchEntryBuilder();\r
-        List<String> groups = new ArrayList<>();\r
-        for (int i = 0; i < GROUPS_IN_IPV6_ADDRESS; i++) {\r
-            groups.add(String.format("X", in.readUnsignedShort()));\r
-        }\r
-        Joiner joiner = Joiner.on(":");\r
-        ipv6AddressBuilder.setIpv6Address(new Ipv6Address(joiner.join(groups)));\r
-        builder.addAugmentation(Ipv6AddressMatchEntry.class, ipv6AddressBuilder.build());\r
-    }\r
-    \r
-    private static void addMetadataAugmentation(MatchEntriesBuilder builder, ByteBuf in) {\r
-        MetadataMatchEntryBuilder metadata = new MetadataMatchEntryBuilder();\r
-        byte[] metadataBytes = new byte[Long.SIZE/Byte.SIZE];\r
-        in.readBytes(metadataBytes);\r
-        metadata.setMetadata(metadataBytes); \r
-        builder.addAugmentation(MetadataMatchEntry.class, metadata.build());\r
-    }\r
-\r
-    private static void addIpv4AddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) {\r
-        final byte GROUPS_IN_IPV4_ADDRESS = 4;\r
-        Ipv4AddressMatchEntryBuilder ipv4AddressBuilder = new Ipv4AddressMatchEntryBuilder();\r
-        List<String> groups = new ArrayList<>();\r
-        for (int i = 0; i < GROUPS_IN_IPV4_ADDRESS; i++) {\r
-            groups.add(Short.toString(in.readUnsignedByte()));\r
-        }\r
-        Joiner joiner = Joiner.on(".");\r
-        ipv4AddressBuilder.setIpv4Address(new Ipv4Address(joiner.join(groups)));\r
-        builder.addAugmentation(Ipv4AddressMatchEntry.class, ipv4AddressBuilder.build());\r
-    }\r
-\r
-    private static void addMacAddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) {\r
-        MacAddressMatchEntryBuilder macAddress = new MacAddressMatchEntryBuilder();\r
-        StringBuffer macToString = new StringBuffer();\r
-        final int macAddressLength = 6;\r
-        for(int i=0; i<macAddressLength ; i++){\r
-            short mac = 0;\r
-            mac = in.readUnsignedByte();\r
-            macToString.append(String.format("%02X", mac));\r
-        }\r
-        macAddress.setMacAddress(new MacAddress(macToString.toString())); \r
-        builder.addAugmentation(MacAddressMatchEntry.class, macAddress.build());\r
-    }\r
-    \r
-    private static void addPortAugmentation(MatchEntriesBuilder builder, ByteBuf in) {\r
-        PortMatchEntryBuilder portBuilder = new PortMatchEntryBuilder();\r
-        portBuilder.setPort(new org.opendaylight.yang.gen.v1.urn.ietf.params.\r
-                xml.ns.yang.ietf.inet.types.rev100924.PortNumber(in.readUnsignedShort()));\r
-        builder.addAugmentation(PortMatchEntry.class, portBuilder.build());\r
-    }\r
-}\r
+/*
+ * Copyright (c) 2013 Pantheon Technologies s.r.o. 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowjava.protocol.impl.util;
+
+import io.netty.buffer.ByteBuf;
+
+import java.util.List;
+
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
+import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
+import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
+import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.StandardMatchType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmMatchType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.grouping.MatchBuilder;
+
+/**
+ * Deserializes ofp_match (OpenFlow v1.3) and its oxm_fields structures
+ * @author timotej.kubas
+ * @author michal.polkorab
+ */
+public class MatchDeserializer implements OFDeserializer<Match>,
+        DeserializerRegistryInjector {
+
+    private DeserializerRegistry registry;
+
+    @Override
+    public Match deserialize(ByteBuf input) {
+        if (input.readableBytes() > 0) {
+            MatchBuilder builder = new MatchBuilder();
+            int type = input.readUnsignedShort();
+            int length = input.readUnsignedShort();
+            switch (type) {
+            case 0:
+                builder.setType(StandardMatchType.class);
+                break;
+            case 1:
+                builder.setType(OxmMatchType.class);
+                break;
+            default:
+                break;
+            }
+            CodeKeyMaker keyMaker = CodeKeyMakerFactory
+                    .createMatchEntriesKeyMaker(EncodeConstants.OF13_VERSION_ID);
+            List<MatchEntry> entries = ListDeserializer.deserializeList(EncodeConstants.OF13_VERSION_ID,
+                    length - 2 * EncodeConstants.SIZE_OF_SHORT_IN_BYTES, input, keyMaker, registry);
+            builder.setMatchEntry(entries);
+            int paddingRemainder = length % EncodeConstants.PADDING;
+            if (paddingRemainder != 0) {
+                input.skipBytes(EncodeConstants.PADDING - paddingRemainder);
+            }
+            return builder.build();
+        }
+        return null;
+    }
+
+    @Override
+    public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
+        this.registry = deserializerRegistry;
+    }
+}