Copyright update
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / util / MatchDeserializer.java
1 /*
2  * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.openflowjava.protocol.impl.util;
10
11 import io.netty.buffer.ByteBuf;
12
13 import java.util.ArrayList;
14 import java.util.List;
15
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6FlowLabel;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.BosMatchEntry;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.BosMatchEntryBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.DscpMatchEntry;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.DscpMatchEntryBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EcnMatchEntry;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EcnMatchEntryBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthTypeMatchEntry;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.EthTypeMatchEntryBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4CodeMatchEntry;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4CodeMatchEntryBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4TypeMatchEntry;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv4TypeMatchEntryBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6CodeMatchEntry;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6CodeMatchEntryBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6TypeMatchEntry;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Icmpv6TypeMatchEntryBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv4AddressMatchEntry;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv4AddressMatchEntryBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv6AddressMatchEntry;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv6AddressMatchEntryBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv6FlabelMatchEntry;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.Ipv6FlabelMatchEntryBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.IsidMatchEntry;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.IsidMatchEntryBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MacAddressMatchEntry;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MacAddressMatchEntryBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaskMatchEntry;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MaskMatchEntryBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataMatchEntry;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MetadataMatchEntryBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsLabelMatchEntry;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.MplsLabelMatchEntryBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OpCodeMatchEntry;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.OpCodeMatchEntryBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortMatchEntry;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortMatchEntryBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntry;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PortNumberMatchEntryBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ProtocolNumberMatchEntry;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.ProtocolNumberMatchEntryBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PseudoFieldMatchEntry;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PseudoFieldMatchEntry.PseudoField;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.PseudoFieldMatchEntryBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TcMatchEntry;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.TcMatchEntryBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanPcpMatchEntry;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanPcpMatchEntryBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanVidMatchEntry;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev131002.VlanVidMatchEntryBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.StandardMatchType;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpOp;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpSha;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpSpa;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpTha;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ArpTpa;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthDst;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthSrc;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.EthType;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.ExperimenterClass;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv4Code;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv4Type;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv6Code;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Icmpv6Type;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPhyPort;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.InPort;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpDscp;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpEcn;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.IpProto;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv4Dst;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv4Src;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Dst;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Exthdr;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Flabel;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdSll;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdTarget;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6NdTll;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Ipv6Src;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Metadata;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsBos;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsLabel;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.MplsTc;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Nxm0Class;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.Nxm1Class;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OpenflowBasicClass;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.OxmMatchType;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.PbbIsid;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.SctpDst;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.SctpSrc;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TcpDst;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TcpSrc;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.TunnelId;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.UdpDst;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.UdpSrc;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.VlanPcp;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.VlanVid;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntries;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.oxm.fields.MatchEntriesBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.match.grouping.Match;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.match.grouping.MatchBuilder;
122 import org.slf4j.Logger;
123 import org.slf4j.LoggerFactory;
124
125 import com.google.common.base.Joiner;
126
127 /**
128  * Deserializes ofp_match (OpenFlow v1.3) and its oxm_fields structures
129  * @author timotej.kubas
130  * @author michal.polkorab
131  */
132 public abstract class MatchDeserializer {
133
134     private static final Logger LOGGER = LoggerFactory.getLogger(MatchDeserializer.class);
135     
136     /**
137      * Creates match
138      * @param in input ByteBuf
139      * @return ofp_match (OpenFlow v1.3)
140      */
141     public static Match createMatch(ByteBuf in) {
142         if (in.readableBytes() > 0) {
143             MatchBuilder builder = new MatchBuilder();
144             int type = in.readUnsignedShort();
145             int length = in.readUnsignedShort();
146             switch (type) {
147             case 0:
148                 builder.setType(StandardMatchType.class);
149                 break;
150             case 1:
151                 builder.setType(OxmMatchType.class);
152                 break;
153             default:
154                 break;
155             }
156             builder.setMatchEntries(createMatchEntries(in, length - 2 * (EncodeConstants.SIZE_OF_SHORT_IN_BYTES)));
157             int paddingRemainder = length % EncodeConstants.PADDING;
158             if (paddingRemainder != 0) {
159                 in.skipBytes(EncodeConstants.PADDING - paddingRemainder);
160             }
161             return builder.build();
162         }
163         return null;
164     }
165     
166     /**
167      * Deserializes single match entry (oxm_field)
168      * @param in input ByteBuf
169      * @param matchLength length of match entry
170      * @return MatchEntriesList list containing one match entry
171      */
172     public static List<MatchEntries> createMatchEntry(ByteBuf in, int matchLength) {
173         return createMatchEntriesInternal(in, matchLength, true);
174     }
175     
176     /**
177      * @param in input ByteBuf
178      * @param matchLength length of match entries
179      * @return MatchEntriesList list of match entries
180      */
181     public static List<MatchEntries> createMatchEntries(ByteBuf in, int matchLength) {
182         return createMatchEntriesInternal(in, matchLength, false);
183     }
184     
185     private static List<MatchEntries> createMatchEntriesInternal(ByteBuf in, int matchLength, boolean oneEntry) {
186         List<MatchEntries> matchEntriesList = new ArrayList<>();
187         int currLength = 0;
188         while(currLength < matchLength) {
189             MatchEntriesBuilder matchEntriesBuilder = new MatchEntriesBuilder(); 
190             switch (in.readUnsignedShort()) { 
191             case 0x0000:
192                         matchEntriesBuilder.setOxmClass(Nxm0Class.class);
193                         break;
194             case 0x0001:
195                         matchEntriesBuilder.setOxmClass(Nxm1Class.class);
196                         break;
197             case 0x8000:
198                         matchEntriesBuilder.setOxmClass(OpenflowBasicClass.class);
199                         break;
200             case 0xFFFF:
201                         matchEntriesBuilder.setOxmClass(ExperimenterClass.class);
202                         break;
203             default:
204                         break;
205             }
206
207             int fieldAndMask = in.readUnsignedByte();
208             boolean hasMask = (fieldAndMask & 1) != 0;
209             matchEntriesBuilder.setHasMask(hasMask);
210             int matchField =  fieldAndMask >> 1;
211             int matchEntryLength = in.readUnsignedByte();
212             currLength += EncodeConstants.SIZE_OF_SHORT_IN_BYTES +
213                     (2 * EncodeConstants.SIZE_OF_BYTE_IN_BYTES) + matchEntryLength;
214             
215             switch(matchField) {
216             case 0: 
217                 matchEntriesBuilder.setOxmMatchField(InPort.class);
218                 PortNumberMatchEntryBuilder port = new PortNumberMatchEntryBuilder();
219                 port.setPortNumber(new PortNumber(in.readUnsignedInt())); 
220                 matchEntriesBuilder.addAugmentation(PortNumberMatchEntry.class, port.build());
221                 break;
222             case 1:
223                 matchEntriesBuilder.setOxmMatchField(InPhyPort.class);
224                 PortNumberMatchEntryBuilder phyPort = new PortNumberMatchEntryBuilder();
225                 phyPort.setPortNumber(new PortNumber(in.readUnsignedInt())); 
226                 matchEntriesBuilder.addAugmentation(PortNumberMatchEntry.class, phyPort.build());
227                 break;
228             case 2:
229                 matchEntriesBuilder.setOxmMatchField(Metadata.class);
230                 addMetadataAugmentation(matchEntriesBuilder, in);
231                 if (hasMask) {
232                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_LONG_IN_BYTES);
233                 }
234                 break;
235             case 3:
236                 matchEntriesBuilder.setOxmMatchField(EthDst.class);
237                 addMacAddressAugmentation(matchEntriesBuilder, in);
238                 if (hasMask) {
239                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_LONG_IN_BYTES);
240                 }
241                 break;
242             case 4:
243                 matchEntriesBuilder.setOxmMatchField(EthSrc.class);
244                 addMacAddressAugmentation(matchEntriesBuilder, in);
245                 if (hasMask) {
246                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_LONG_IN_BYTES);
247                 }
248                 break;
249             case 5:
250                 matchEntriesBuilder.setOxmMatchField(EthType.class);
251                 EthTypeMatchEntryBuilder ethertypeBuilder = new EthTypeMatchEntryBuilder();
252                 ethertypeBuilder.setEthType(new EtherType(in.readUnsignedShort()));
253                 matchEntriesBuilder.addAugmentation(EthTypeMatchEntry.class, ethertypeBuilder.build());
254                 break;
255             case 6:
256                 matchEntriesBuilder.setOxmMatchField(VlanVid.class);
257                 VlanVidMatchEntryBuilder vlanVidBuilder = new VlanVidMatchEntryBuilder();
258                 int vidEntryValue = in.readUnsignedShort();
259                 vlanVidBuilder.setCfiBit((vidEntryValue & (1 << 12)) != 0); // cfi is 13-th bit
260                 vlanVidBuilder.setVlanVid(vidEntryValue & ((1 << 12) - 1)); // value without 13-th bit
261                 matchEntriesBuilder.addAugmentation(VlanVidMatchEntry.class, vlanVidBuilder.build());
262                 if (hasMask) {
263                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
264                 }
265                 break;
266             case 7:
267                 matchEntriesBuilder.setOxmMatchField(VlanPcp.class);
268                 VlanPcpMatchEntryBuilder vlanPcpBuilder = new VlanPcpMatchEntryBuilder();
269                 vlanPcpBuilder.setVlanPcp(in.readUnsignedByte());
270                 matchEntriesBuilder.addAugmentation(VlanPcpMatchEntry.class, vlanPcpBuilder.build());
271                 break;
272             case 8:
273                 matchEntriesBuilder.setOxmMatchField(IpDscp.class);
274                 DscpMatchEntryBuilder dscpBuilder = new DscpMatchEntryBuilder();
275                 dscpBuilder.setDscp(new Dscp(in.readUnsignedByte()));
276                 matchEntriesBuilder.addAugmentation(DscpMatchEntry.class, dscpBuilder.build());
277                 break;
278             case 9:
279                 matchEntriesBuilder.setOxmMatchField(IpEcn.class);
280                 EcnMatchEntryBuilder ecnBuilder = new EcnMatchEntryBuilder();
281                 ecnBuilder.setEcn(in.readUnsignedByte());
282                 matchEntriesBuilder.addAugmentation(EcnMatchEntry.class, ecnBuilder.build());
283                 break;
284             case 10:
285                 matchEntriesBuilder.setOxmMatchField(IpProto.class);
286                 ProtocolNumberMatchEntryBuilder protoNumberBuilder = new ProtocolNumberMatchEntryBuilder();
287                 protoNumberBuilder.setProtocolNumber(in.readUnsignedByte());
288                 matchEntriesBuilder.addAugmentation(ProtocolNumberMatchEntry.class, protoNumberBuilder.build());
289                 break;
290             case 11:
291                 matchEntriesBuilder.setOxmMatchField(Ipv4Src.class);
292                 LOGGER.warn("IPV4address(ipv4src): received but possible wrong deserialization");
293                 addIpv4AddressAugmentation(matchEntriesBuilder, in);
294                 if (hasMask) {
295                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_INT_IN_BYTES);
296                 }
297                 break;
298             case 12:
299                 matchEntriesBuilder.setOxmMatchField(Ipv4Dst.class);
300                 LOGGER.warn("IPV4address(ipv4dst): received but possible wrong deserialization");
301                 addIpv4AddressAugmentation(matchEntriesBuilder, in);
302                 if (hasMask) {
303                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_INT_IN_BYTES);
304                 }
305                 break;
306             case 13:
307                 matchEntriesBuilder.setOxmMatchField(TcpSrc.class);
308                 addPortAugmentation(null, in);
309                 break;
310             case 14:
311                 matchEntriesBuilder.setOxmMatchField(TcpDst.class);
312                 addPortAugmentation(null, in);
313                 break;
314             case 15:
315                 matchEntriesBuilder.setOxmMatchField(UdpSrc.class);
316                 addPortAugmentation(null, in);
317                 break;
318             case 16:
319                 matchEntriesBuilder.setOxmMatchField(UdpDst.class);
320                 addPortAugmentation(null, in);
321                 break;
322             case 17:
323                 matchEntriesBuilder.setOxmMatchField(SctpSrc.class);
324                 addPortAugmentation(null, in);
325                 break;
326             case 18:
327                 matchEntriesBuilder.setOxmMatchField(SctpDst.class);
328                 addPortAugmentation(null, in);
329                 break;
330             case 19:
331                 matchEntriesBuilder.setOxmMatchField(Icmpv4Type.class);
332                 Icmpv4TypeMatchEntryBuilder icmpv4TypeBuilder = new Icmpv4TypeMatchEntryBuilder();
333                 icmpv4TypeBuilder.setIcmpv4Type(in.readUnsignedByte());
334                 matchEntriesBuilder.addAugmentation(Icmpv4TypeMatchEntry.class, icmpv4TypeBuilder.build());
335                 break;
336             case 20:
337                 matchEntriesBuilder.setOxmMatchField(Icmpv4Code.class);
338                 Icmpv4CodeMatchEntryBuilder icmpv4CodeBuilder = new Icmpv4CodeMatchEntryBuilder();
339                 icmpv4CodeBuilder.setIcmpv4Code(in.readUnsignedByte());
340                 matchEntriesBuilder.addAugmentation(Icmpv4CodeMatchEntry.class, icmpv4CodeBuilder.build());
341                 break;
342             case 21:
343                 matchEntriesBuilder.setOxmMatchField(ArpOp.class);
344                 OpCodeMatchEntryBuilder opcodeBuilder = new OpCodeMatchEntryBuilder();
345                 opcodeBuilder.setOpCode(in.readUnsignedShort());
346                 matchEntriesBuilder.addAugmentation(OpCodeMatchEntry.class, opcodeBuilder.build());
347                 break;
348             case 22:
349                 matchEntriesBuilder.setOxmMatchField(ArpSpa.class);
350                 LOGGER.warn("IPV4address(arpspa): received but possible wrong deserialization");
351                 addIpv4AddressAugmentation(matchEntriesBuilder, in);
352                 if (hasMask) {
353                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_INT_IN_BYTES);
354                 }
355                 break;
356             case 23:
357                 matchEntriesBuilder.setOxmMatchField(ArpTpa.class);
358                 LOGGER.warn("IPV4address(arptpa): received but possible wrong deserialization");
359                 addIpv4AddressAugmentation(matchEntriesBuilder, in);
360                 if (hasMask) {
361                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_INT_IN_BYTES);
362                 }
363                 break;
364             case 24:
365                 matchEntriesBuilder.setOxmMatchField(ArpSha.class);
366                 addMacAddressAugmentation(matchEntriesBuilder, in);
367                 if (hasMask) {
368                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_LONG_IN_BYTES);
369                 }
370                 break;
371             case 25:
372                 matchEntriesBuilder.setOxmMatchField(ArpTha.class);
373                 addMacAddressAugmentation(matchEntriesBuilder, in);
374                 if (hasMask) {
375                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_LONG_IN_BYTES);
376                 }
377                 break;
378             case 26:
379                 matchEntriesBuilder.setOxmMatchField(Ipv6Src.class);
380                 // TODO - ipv6address - check format with tests
381                 LOGGER.warn("IPV6address(Ipv6Src): received but possible wrong deserialization");
382                 addIpv6AddressAugmentation(matchEntriesBuilder, in);
383                 if (hasMask) {
384                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_IPV6_ADDRESS_IN_BYTES);
385                 }
386                 break;
387             case 27:
388                 matchEntriesBuilder.setOxmMatchField(Ipv6Dst.class);
389                 // TODO - ipv6address - check format with tests
390                 LOGGER.warn("IPV6address(Ipv6Dst): received but possible wrong deserialization");
391                 addIpv6AddressAugmentation(matchEntriesBuilder, in);
392                 if (hasMask) {
393                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_IPV6_ADDRESS_IN_BYTES);
394                 }
395                 break;
396             case 28:
397                 matchEntriesBuilder.setOxmMatchField(Ipv6Flabel.class);
398                 Ipv6FlabelMatchEntryBuilder ipv6FlabelBuilder = new Ipv6FlabelMatchEntryBuilder();
399                 ipv6FlabelBuilder.setIpv6Flabel(new Ipv6FlowLabel(in.readUnsignedInt()));
400                 matchEntriesBuilder.addAugmentation(Ipv6FlabelMatchEntry.class, ipv6FlabelBuilder.build());
401                 if (hasMask) {
402                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_INT_IN_BYTES);
403                 }
404                 break;
405             case 29:
406                 matchEntriesBuilder.setOxmMatchField(Icmpv6Type.class);
407                 Icmpv6TypeMatchEntryBuilder icmpv6TypeBuilder = new Icmpv6TypeMatchEntryBuilder();
408                 icmpv6TypeBuilder.setIcmpv6Type(in.readUnsignedByte());
409                 matchEntriesBuilder.addAugmentation(Icmpv6TypeMatchEntry.class, icmpv6TypeBuilder.build());
410                 break;
411             case 30:
412                 matchEntriesBuilder.setOxmMatchField(Icmpv6Code.class);
413                 Icmpv6CodeMatchEntryBuilder icmpv6CodeBuilder = new Icmpv6CodeMatchEntryBuilder();
414                 icmpv6CodeBuilder.setIcmpv6Code(in.readUnsignedByte());
415                 matchEntriesBuilder.addAugmentation(Icmpv6CodeMatchEntry.class, icmpv6CodeBuilder.build());
416                 break;
417             case 31:
418                 matchEntriesBuilder.setOxmMatchField(Ipv6NdTarget.class);
419                 // TODO - ipv6address - check format with tests
420                 LOGGER.warn("IPV6address(Ipv6NdTarget): received but possible wrong deserialization");
421                 addIpv6AddressAugmentation(matchEntriesBuilder, in);
422                 break;
423             case 32:
424                 matchEntriesBuilder.setOxmMatchField(Ipv6NdSll.class);
425                 addMacAddressAugmentation(matchEntriesBuilder, in);
426                 break;
427             case 33:
428                 matchEntriesBuilder.setOxmMatchField(Ipv6NdTll.class);
429                 addMacAddressAugmentation(matchEntriesBuilder, in);
430                 break;
431             case 34:
432                 matchEntriesBuilder.setOxmMatchField(MplsLabel.class);
433                 MplsLabelMatchEntryBuilder mplsLabelBuilder = new MplsLabelMatchEntryBuilder();
434                 mplsLabelBuilder.setMplsLabel(in.readUnsignedInt());
435                 matchEntriesBuilder.addAugmentation(MplsLabelMatchEntry.class, mplsLabelBuilder.build());
436                 break;
437             case 35:
438                 matchEntriesBuilder.setOxmMatchField(MplsTc.class);
439                 TcMatchEntryBuilder tcBuilder = new TcMatchEntryBuilder();
440                 tcBuilder.setTc(in.readUnsignedByte());
441                 matchEntriesBuilder.addAugmentation(TcMatchEntry.class, tcBuilder.build());
442                 break;
443             case 36:
444                 matchEntriesBuilder.setOxmMatchField(MplsBos.class);
445                 BosMatchEntryBuilder bosBuilder = new BosMatchEntryBuilder();
446                 if (in.readUnsignedByte() != 0) {
447                     bosBuilder.setBos(true);
448                 } else {
449                     bosBuilder.setBos(false);
450                 }
451                 matchEntriesBuilder.addAugmentation(BosMatchEntry.class, bosBuilder.build());
452                 break;
453             case 37:
454                 matchEntriesBuilder.setOxmMatchField(PbbIsid.class);
455                 IsidMatchEntryBuilder isidBuilder = new IsidMatchEntryBuilder();
456                 isidBuilder.setIsid(in.readUnsignedInt());
457                 matchEntriesBuilder.addAugmentation(IsidMatchEntry.class, isidBuilder.build());
458                 if (hasMask) {
459                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_INT_IN_BYTES);
460                 }
461                 break;
462             case 38:
463                 matchEntriesBuilder.setOxmMatchField(TunnelId.class);
464                 addMetadataAugmentation(matchEntriesBuilder, in);
465                 if (hasMask) {
466                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_LONG_IN_BYTES);
467                 }
468                 break;
469             case 39:
470                 matchEntriesBuilder.setOxmMatchField(Ipv6Exthdr.class);
471                 PseudoFieldMatchEntryBuilder pseudoBuilder = new PseudoFieldMatchEntryBuilder();
472                 int bitmap = in.readUnsignedShort();
473                 final Boolean NONEXT = ((bitmap) & (1<<0)) != 0;
474                 final Boolean ESP = ((bitmap) & (1<<1)) != 0;
475                 final Boolean AUTH = ((bitmap) & (1<<2)) != 0;
476                 final Boolean DEST = ((bitmap) & (1<<3)) != 0;
477                 final Boolean FRAG = ((bitmap) & (1<<4)) != 0;
478                 final Boolean ROUTER = ((bitmap) & (1<<5)) != 0;
479                 final Boolean HOP = ((bitmap) & (1<<6)) != 0;
480                 final Boolean UNREP = ((bitmap) & (1<<7)) != 0;
481                 final Boolean UNSEQ = ((bitmap) & (1<<8)) != 0;
482                 pseudoBuilder.setPseudoField(new PseudoField(AUTH, DEST, ESP, FRAG, HOP, NONEXT, ROUTER, UNREP, UNSEQ));
483                 matchEntriesBuilder.addAugmentation(PseudoFieldMatchEntry.class, pseudoBuilder.build());
484                 if (hasMask) {
485                     addMaskAugmentation(matchEntriesBuilder, in, EncodeConstants.SIZE_OF_SHORT_IN_BYTES);
486                 }
487                 break;
488             default: 
489                 break;
490             }
491           matchEntriesList.add(matchEntriesBuilder.build());
492           if (oneEntry) {
493               break;
494           }
495         }
496         if ((matchLength - currLength) > 0) {
497             in.skipBytes(matchLength - currLength);
498         }
499         return matchEntriesList;
500     }
501
502     private static void addMaskAugmentation(MatchEntriesBuilder builder, ByteBuf in, int matchEntryLength) {
503         MaskMatchEntryBuilder maskBuilder = new MaskMatchEntryBuilder();
504         byte[] mask = new byte[matchEntryLength];
505         in.readBytes(mask);
506         maskBuilder.setMask(mask);
507         builder.addAugmentation(MaskMatchEntry.class, maskBuilder.build());
508     }
509
510     private static void addIpv6AddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) {
511         Ipv6AddressMatchEntryBuilder ipv6AddressBuilder = new Ipv6AddressMatchEntryBuilder();
512         List<String> groups = new ArrayList<>();
513         for (int i = 0; i < EncodeConstants.GROUPS_IN_IPV6_ADDRESS; i++) {
514             groups.add(String.format("X", in.readUnsignedShort()));
515         }
516         Joiner joiner = Joiner.on(":");
517         ipv6AddressBuilder.setIpv6Address(new Ipv6Address(joiner.join(groups)));
518         builder.addAugmentation(Ipv6AddressMatchEntry.class, ipv6AddressBuilder.build());
519     }
520     
521     private static void addMetadataAugmentation(MatchEntriesBuilder builder, ByteBuf in) {
522         MetadataMatchEntryBuilder metadata = new MetadataMatchEntryBuilder();
523         byte[] metadataBytes = new byte[Long.SIZE/Byte.SIZE];
524         in.readBytes(metadataBytes);
525         metadata.setMetadata(metadataBytes); 
526         builder.addAugmentation(MetadataMatchEntry.class, metadata.build());
527     }
528
529     private static void addIpv4AddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) {
530         Ipv4AddressMatchEntryBuilder ipv4AddressBuilder = new Ipv4AddressMatchEntryBuilder();
531         List<String> groups = new ArrayList<>();
532         for (int i = 0; i < EncodeConstants.GROUPS_IN_IPV4_ADDRESS; i++) {
533             groups.add(Short.toString(in.readUnsignedByte()));
534         }
535         Joiner joiner = Joiner.on(".");
536         ipv4AddressBuilder.setIpv4Address(new Ipv4Address(joiner.join(groups)));
537         builder.addAugmentation(Ipv4AddressMatchEntry.class, ipv4AddressBuilder.build());
538     }
539
540     private static void addMacAddressAugmentation(MatchEntriesBuilder builder, ByteBuf in) {
541         MacAddressMatchEntryBuilder macAddress = new MacAddressMatchEntryBuilder();
542         byte[] address = new byte[EncodeConstants.MAC_ADDRESS_LENGTH];
543         in.readBytes(address);
544         macAddress.setMacAddress(new MacAddress(ByteBufUtils.macAddressToString(address)));
545         builder.addAugmentation(MacAddressMatchEntry.class, macAddress.build());
546     }
547     
548     private static void addPortAugmentation(MatchEntriesBuilder builder, ByteBuf in) {
549         PortMatchEntryBuilder portBuilder = new PortMatchEntryBuilder();
550         portBuilder.setPort(new org.opendaylight.yang.gen.v1.urn.ietf.params.
551                 xml.ns.yang.ietf.inet.types.rev100924.PortNumber(in.readUnsignedShort()));
552         builder.addAugmentation(PortMatchEntry.class, portBuilder.build());
553     }
554 }