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