Rooted out the last of the ReflectionToStringBuilder usage
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / vendorextension / v6extension / V6Match.java
1
2 /*
3  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9
10 package org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension;
11
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import java.nio.ByteBuffer;
16 import java.util.Arrays;
17
18 import org.opendaylight.controller.sal.utils.HexEncode;
19 import org.openflow.protocol.OFMatch;
20 import org.openflow.util.U16;
21 import org.openflow.util.U8;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
24
25 /**
26  * This Class forms the vendor specific IPv6 Flow Match messages as well as
27  * processes the vendor specific IPv6 Stats Reply message.
28  *
29  * For message creation, it parses the user entered IPv6 match fields, creates
30  * a sub-message for each field which are later used to form the complete
31  * message.
32  *
33  * For message processing, it parses the incoming message and reads each field
34  * of the message and stores in appropriate field of V6Match object.
35  *
36  *
37  */
38 public class V6Match extends OFMatch implements Cloneable {
39     private static final Logger logger = LoggerFactory.getLogger(V6Match.class);
40     private static final long serialVersionUID = 1L;
41     protected InetAddress nwSrc;
42     protected InetAddress nwDst;
43     protected short inputPortMask;
44     protected byte[] dataLayerSourceMask;
45     protected byte[] dataLayerDestinationMask;
46     protected short dataLayerVirtualLanMask;
47     protected byte dataLayerVirtualLanPriorityCodePointMask;
48     protected short dataLayerTypeMask;
49     protected byte networkTypeOfServiceMask;
50     protected byte networkProtocolMask;
51     protected InetAddress networkSourceMask;
52     protected InetAddress networkDestinationMask;
53     protected short transportSourceMask;
54     protected short transportDestinationMask;
55     protected short srcIPv6SubnetMaskbits;
56     protected short dstIPv6SubnetMaskbits;
57
58     protected MatchFieldState inputPortState;
59     protected MatchFieldState dlSourceState;
60     protected MatchFieldState dlDestState;
61     protected MatchFieldState dlVlanState;
62     protected MatchFieldState ethTypeState;
63     protected MatchFieldState nwTosState;
64     protected MatchFieldState nwProtoState;
65     protected MatchFieldState nwSrcState;
66     protected MatchFieldState nwDstState;
67     protected MatchFieldState tpSrcState;
68     protected MatchFieldState tpDstState;
69     protected short match_len = 0;
70     protected short pad_size = 0;
71
72     private static int IPV6_EXT_MIN_HDR_LEN = 36;
73
74     private enum MatchFieldState {
75         MATCH_ABSENT, MATCH_FIELD_ONLY, MATCH_FIELD_WITH_MASK
76     }
77
78     private enum OF_Match_Types {
79         MATCH_OF_IN_PORT(0), MATCH_OF_ETH_DST(1), MATCH_OF_ETH_SRC(2), MATCH_OF_ETH_TYPE(
80                 3), MATCH_OF_VLAN_TCI(4), MATCH_OF_IP_TOS(5), MATCH_OF_IP_PROTO(
81                 6), MATCH_OF_IP_SRC(7), MATCH_OF_IP_DST(8), MATCH_OF_TCP_SRC(9), MATCH_OF_TCP_DST(
82                 10), MATCH_OF_UDP_SRC(11), MATCH_OF_UDP_DST(12), MATCH_OF_ICMTP_TYPE(
83                 13), MATCH_OF_ICMP_CODE(14), MATCH_OF_ARP_OP(15);
84
85         private int value;
86
87         private OF_Match_Types(int value) {
88             this.value = value;
89         }
90
91         public int getValue() {
92             return this.value;
93         }
94     }
95
96     private enum IPv6Extension_Match_Types {
97         MATCH_IPV6EXT_TUN_ID(16), MATCH_IPV6EXT_ARP_SHA(17), MATCH_IPV6EXT_ARP_THA(
98                 18), MATCH_IPV6EXT_IPV6_SRC(19), MATCH_IPV6EXT_IPV6_DST(20);
99
100         private int value;
101
102         private IPv6Extension_Match_Types(int value) {
103             this.value = value;
104         }
105
106         public int getValue() {
107             return value;
108         }
109     }
110
111     public enum Extension_Types {
112         OF_10(0), IPV6EXT(1);
113
114         protected int value;
115
116         private Extension_Types(int value) {
117             this.value = value;
118         }
119
120         public int getValue() {
121             return value;
122         }
123     }
124
125     public V6Match() {
126         super();
127
128         this.nwSrc = null;
129         this.nwDst = null;
130
131         this.inputPortMask = 0;
132         this.dataLayerSourceMask = null;
133         this.dataLayerDestinationMask = null;
134         this.dataLayerTypeMask = 0;
135         this.dataLayerVirtualLanMask = 0;
136         this.dataLayerVirtualLanPriorityCodePointMask = 0;
137         this.networkDestinationMask = null;
138         this.networkSourceMask = null;
139         this.networkTypeOfServiceMask = 0;
140         this.networkProtocolMask = 0;
141         this.transportSourceMask = 0;
142         this.transportDestinationMask = 0;
143
144         this.inputPortState = MatchFieldState.MATCH_ABSENT;
145         this.dlSourceState = MatchFieldState.MATCH_ABSENT;
146         this.dlDestState = MatchFieldState.MATCH_ABSENT;
147         this.dlVlanState = MatchFieldState.MATCH_ABSENT;
148         this.ethTypeState = MatchFieldState.MATCH_ABSENT;
149         this.nwTosState = MatchFieldState.MATCH_ABSENT;
150         this.nwProtoState = MatchFieldState.MATCH_ABSENT;
151         this.nwSrcState = MatchFieldState.MATCH_ABSENT;
152         this.nwDstState = MatchFieldState.MATCH_ABSENT;
153         this.tpSrcState = MatchFieldState.MATCH_ABSENT;
154         this.tpDstState = MatchFieldState.MATCH_ABSENT;
155
156         this.match_len = 0;
157         this.pad_size = 0;
158     }
159
160     public V6Match(OFMatch match) {
161         super();
162         this.match_len = 0;
163         this.pad_size = 0;
164
165         this.networkSourceMask = null;
166         if (match.getNetworkSource() != 0) {
167             InetAddress address = null;
168             try {
169                 address = InetAddress.getByAddress(ByteBuffer.allocate(4)
170                         .putInt(match.getNetworkSource()).array());
171             } catch (UnknownHostException e) {
172                 logger.error("",e);
173             }
174             this.setNetworkSource(address, null);
175         } else {
176             this.nwSrc = null;
177             this.nwSrcState = MatchFieldState.MATCH_ABSENT;
178         }
179
180         this.networkDestinationMask = null;
181         if (match.getNetworkDestination() != 0) {
182             InetAddress address = null;
183             try {
184                 address = InetAddress.getByAddress(ByteBuffer.allocate(4)
185                         .putInt(match.getNetworkDestination()).array());
186             } catch (UnknownHostException e) {
187                 logger.error("",e);
188             }
189             this.setNetworkDestination(address, null);
190         } else {
191             this.nwDst = null;
192             this.nwDstState = MatchFieldState.MATCH_ABSENT;
193         }
194
195         this.inputPortMask = 0;
196         if (match.getInputPort() != 0) {
197             this.setInputPort(match.getInputPort(), (short) 0);
198         } else {
199             this.inputPortMask = 0;
200             this.inputPortState = MatchFieldState.MATCH_ABSENT;
201         }
202
203         this.dataLayerSourceMask = null;
204         if (match.getDataLayerSource() != null) {
205             this.setDataLayerSource(match.getDataLayerSource(), null);
206         } else {
207             this.dataLayerSource = null;
208             this.dlSourceState = MatchFieldState.MATCH_ABSENT;
209         }
210         this.dataLayerDestinationMask = null;
211         if (match.getDataLayerDestination() != null) {
212             this.setDataLayerDestination(match.getDataLayerDestination(), null);
213         } else {
214             this.dataLayerDestination = null;
215             this.dlDestState = MatchFieldState.MATCH_ABSENT;
216         }
217
218         this.dataLayerTypeMask = 0;
219         if (match.getDataLayerType() != 0) {
220             this.setDataLayerType(match.getDataLayerType(), (short) 0);
221         } else {
222             this.dataLayerType = 0;
223             this.ethTypeState = MatchFieldState.MATCH_ABSENT;
224         }
225
226         this.dataLayerVirtualLanMask = 0;
227         if (match.getDataLayerVirtualLan() != 0) {
228             this.setDataLayerVirtualLan(match.getDataLayerVirtualLan(),
229                     (short) 0);
230         } else {
231             this.dataLayerVirtualLan = 0;
232             this.dlVlanState = MatchFieldState.MATCH_ABSENT;
233         }
234
235         this.dataLayerVirtualLanPriorityCodePointMask = 0;
236         if (match.getDataLayerVirtualLanPriorityCodePoint() != 0) {
237             this.setDataLayerVirtualLanPriorityCodePoint(match
238                     .getDataLayerVirtualLanPriorityCodePoint(), (byte) 0);
239         } else {
240             this.dataLayerVirtualLanPriorityCodePoint = 0;
241         }
242
243         this.networkProtocolMask = 0;
244         if (match.getNetworkProtocol() != 0) {
245             this.setNetworkProtocol(this.networkProtocol = match
246                     .getNetworkProtocol(), (byte) 0);
247         } else {
248             this.networkProtocol = 0;
249             this.nwProtoState = MatchFieldState.MATCH_ABSENT;
250         }
251
252         this.networkTypeOfServiceMask = 0;
253         if (match.getNetworkTypeOfService() != 0) {
254             this.setNetworkTypeOfService(this.networkTypeOfService = match
255                     .getNetworkTypeOfService(), (byte) 0);
256         } else {
257             this.networkTypeOfService = match.getNetworkTypeOfService();
258             this.nwTosState = MatchFieldState.MATCH_ABSENT;
259         }
260
261         this.transportSourceMask = 0;
262         if (match.getTransportSource() != 0) {
263             this.setTransportSource(match.getTransportSource(), (short) 0);
264         } else {
265             this.transportSource = 0;
266             this.tpSrcState = MatchFieldState.MATCH_ABSENT;
267         }
268
269         this.transportDestinationMask = 0;
270         if (match.getTransportDestination() != 0) {
271             this.setTransportDestination(match.getTransportDestination(),
272                     (short) 0);
273         } else {
274             this.transportDestination = 0;
275             this.tpDstState = MatchFieldState.MATCH_ABSENT;
276         }
277
278         this.setWildcards(match.getWildcards());
279     }
280
281     private enum IPProtocols {
282         ICMP(1), TCP(6), UDP(17), ICMPV6(58);
283
284         private int protocol;
285
286         private IPProtocols(int value) {
287             this.protocol = value;
288         }
289
290         private byte getValue() {
291             return (byte) this.protocol;
292         }
293     }
294
295     public short getIPv6MatchLen() {
296         return match_len;
297     }
298
299     public int getIPv6ExtMinHdrLen() {
300         return IPV6_EXT_MIN_HDR_LEN;
301     }
302
303     public short getPadSize() {
304         return (short) (((match_len + 7) / 8) * 8 - match_len);
305     }
306
307     private int getIPv6ExtensionMatchHeader(Extension_Types extType, int field,
308             int has_mask, int length) {
309         return (((extType.getValue() & 0x0000ffff) << 16)
310                 | ((field & 0x0000007f) << 9) | ((has_mask & 0x00000001) << 8) | (length & 0x000000ff));
311     }
312
313     private byte[] getIPv6ExtensionPortMatchMsg(short port) {
314         ByteBuffer ipv6ext_port_msg = ByteBuffer.allocate(6);
315         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
316                 OF_Match_Types.MATCH_OF_IN_PORT.getValue(), 0, 2);
317         ipv6ext_port_msg.putInt(nxm_header);
318         ipv6ext_port_msg.putShort(port);
319         return (ipv6ext_port_msg.array());
320     }
321
322     private byte[] getIPv6ExtensionDestMacMatchMsg(byte[] destMac) {
323         ByteBuffer ipv6ext_destmac_msg = ByteBuffer.allocate(10);
324         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
325                 OF_Match_Types.MATCH_OF_ETH_DST.getValue(), 0, 6);
326         ipv6ext_destmac_msg.putInt(nxm_header);
327         ipv6ext_destmac_msg.put(destMac);
328         return (ipv6ext_destmac_msg.array());
329     }
330
331     private byte[] getIPv6ExtensionSrcMacMatchMsg(byte[] srcMac) {
332         ByteBuffer ipv6ext_srcmac_msg = ByteBuffer.allocate(10);
333         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
334                 OF_Match_Types.MATCH_OF_ETH_SRC.getValue(), 0, 6);
335         ipv6ext_srcmac_msg.putInt(nxm_header);
336         ipv6ext_srcmac_msg.put(srcMac);
337         return (ipv6ext_srcmac_msg.array());
338     }
339
340     private byte[] getIPv6ExtensionEtherTypeMatchMsg(short EtherType) {
341         ByteBuffer ipv6ext_etype_msg = ByteBuffer.allocate(6);
342         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
343                 OF_Match_Types.MATCH_OF_ETH_TYPE.getValue(), 0, 2);
344         ipv6ext_etype_msg.putInt(nxm_header);
345         ipv6ext_etype_msg.putShort(EtherType);
346         return (ipv6ext_etype_msg.array());
347     }
348
349     private byte[] getIPv6ExtensionVlanIDMatchMsg(short VLAN) {
350         ByteBuffer ipv6ext_vlanid_msg = ByteBuffer.allocate(6);
351         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
352                 OF_Match_Types.MATCH_OF_VLAN_TCI.getValue(), 0, 2);
353         ipv6ext_vlanid_msg.putInt(nxm_header);
354         ipv6ext_vlanid_msg.putShort(VLAN);
355         return (ipv6ext_vlanid_msg.array());
356     }
357
358     private byte[] getIPv6ExtensionSrcIPv6MatchMsg(byte[] srcIpv6) {
359         ByteBuffer ipv6ext_ipv6_msg = ByteBuffer.allocate(20);
360         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.IPV6EXT,
361                 IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_SRC.getValue(), 0,
362                 16);
363         ipv6ext_ipv6_msg.putInt(nxm_header);
364         ipv6ext_ipv6_msg.put(srcIpv6);
365         return (ipv6ext_ipv6_msg.array());
366     }
367
368     private byte[] getIPv6ExtensionSrcIPv6MatchwithMaskMsg(byte[] srcIpv6,
369             short masklen) {
370         ByteBuffer ipv6ext_ipv6_msg = ByteBuffer.allocate(36);
371         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.IPV6EXT,
372                 IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_SRC.getValue(), 1,
373                 32);
374         ipv6ext_ipv6_msg.putInt(nxm_header);
375         ipv6ext_ipv6_msg.put(srcIpv6);
376         byte[] ipv6_mask = getIPv6NetworkMaskinBytes(masklen);
377         ipv6ext_ipv6_msg.put(ipv6_mask);
378         return (ipv6ext_ipv6_msg.array());
379     }
380
381     private byte[] getIPv6ExtensionDstIPv6MatchMsg(byte[] dstIpv6) {
382         ByteBuffer ipv6ext_ipv6_msg = ByteBuffer.allocate(20);
383         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.IPV6EXT,
384                 IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_DST.getValue(), 0,
385                 16);
386         ipv6ext_ipv6_msg.putInt(nxm_header);
387         ipv6ext_ipv6_msg.put(dstIpv6);
388         return (ipv6ext_ipv6_msg.array());
389     }
390
391     private byte[] getIPv6ExtensionDstIPv6MatchwithMaskMsg(byte[] dstIpv6,
392             short masklen) {
393         ByteBuffer ipv6ext_ipv6_msg = ByteBuffer.allocate(36);
394         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.IPV6EXT,
395                 IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_DST.getValue(), 1,
396                 32);
397         ipv6ext_ipv6_msg.putInt(nxm_header);
398         ipv6ext_ipv6_msg.put(dstIpv6);
399         byte[] ipv6_mask = getIPv6NetworkMaskinBytes(masklen);
400         ipv6ext_ipv6_msg.put(ipv6_mask);
401         return (ipv6ext_ipv6_msg.array());
402     }
403
404     private byte[] getIPv6ExtensionProtocolMatchMsg(byte protocol) {
405         ByteBuffer ipv6ext_proto_msg = ByteBuffer.allocate(5);
406         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
407                 OF_Match_Types.MATCH_OF_IP_PROTO.getValue(), 0, 1);
408         if (protocol == 0) {
409             return null;
410         }
411         ipv6ext_proto_msg.putInt(nxm_header);
412         if (protocol == IPProtocols.ICMP.getValue()) {
413             /*
414              * The front end  passes the same protocol type values for IPv4
415              * and IPv6 flows. For the Protocol types we allow in our GUI
416              * (ICMP, TCP, UDP), ICMP is the only one which is different for
417              * IPv6. It is 1 for v4 and 58 for v6 Therefore, we overwrite it
418              * here.
419              */
420             protocol = IPProtocols.ICMPV6.getValue();
421         }
422         ipv6ext_proto_msg.put(protocol);
423         return (ipv6ext_proto_msg.array());
424     }
425
426     private byte[] getIPv6ExtensionTOSMatchMsg(byte tos) {
427         ByteBuffer ipv6ext_tos_msg = ByteBuffer.allocate(5);
428         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
429                 OF_Match_Types.MATCH_OF_IP_TOS.getValue(), 0, 1);
430         ipv6ext_tos_msg.putInt(nxm_header);
431         ipv6ext_tos_msg.put(tos);
432         return (ipv6ext_tos_msg.array());
433     }
434
435     private byte[] getIPv6ExtensionTCPSrcPortMatchMsg(short src_port) {
436         ByteBuffer ipv6ext_tcp_srcport_msg = ByteBuffer.allocate(6);
437         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
438                 OF_Match_Types.MATCH_OF_TCP_SRC.getValue(), 0, 2);
439         ipv6ext_tcp_srcport_msg.putInt(nxm_header);
440         ipv6ext_tcp_srcport_msg.putShort(src_port);
441         return (ipv6ext_tcp_srcport_msg.array());
442     }
443
444     private byte[] getIPv6ExtensionTCPDstPortMatchMsg(short dst_port) {
445         ByteBuffer ipv6ext_tcp_dstport_msg = ByteBuffer.allocate(6);
446         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
447                 OF_Match_Types.MATCH_OF_TCP_DST.getValue(), 0, 2);
448         ipv6ext_tcp_dstport_msg.putInt(nxm_header);
449         ipv6ext_tcp_dstport_msg.putShort(dst_port);
450         return (ipv6ext_tcp_dstport_msg.array());
451     }
452
453     private byte[] getIPv6ExtensionUDPSrcPortMatchMsg(short src_port) {
454         ByteBuffer ipv6ext_udp_srcport_msg = ByteBuffer.allocate(6);
455         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
456                 OF_Match_Types.MATCH_OF_UDP_SRC.getValue(), 0, 2);
457         ipv6ext_udp_srcport_msg.putInt(nxm_header);
458         ipv6ext_udp_srcport_msg.putShort(src_port);
459         return (ipv6ext_udp_srcport_msg.array());
460     }
461
462     private byte[] getIPv6ExtensionUDPDstPortMatchMsg(short dst_port) {
463         ByteBuffer ipv6ext_udp_dstport_msg = ByteBuffer.allocate(6);
464         int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
465                 OF_Match_Types.MATCH_OF_UDP_DST.getValue(), 0, 2);
466         ipv6ext_udp_dstport_msg.putInt(nxm_header);
467         ipv6ext_udp_dstport_msg.putShort(dst_port);
468         return (ipv6ext_udp_dstport_msg.array());
469     }
470
471     /**
472      * Sets this (V6Match) object's member variables based on a comma-separated key=value pair similar to OFMatch's fromString.
473      *
474      * @param match a key=value comma separated string.
475      */
476     @Override
477     public void fromString(String match) throws IllegalArgumentException {
478         if (match.equals("") || match.equalsIgnoreCase("any")
479                 || match.equalsIgnoreCase("all") || match.equals("[]"))
480             match = "OFMatch[]";
481         String[] tokens = match.split("[\\[,\\]]");
482         String[] values;
483         int initArg = 0;
484         if (tokens[0].equals("OFMatch"))
485             initArg = 1;
486         this.wildcards = OFPFW_ALL;
487         int i;
488         for (i = initArg; i < tokens.length; i++) {
489             values = tokens[i].split("=");
490             if (values.length != 2)
491                 throw new IllegalArgumentException("Token " + tokens[i]
492                         + " does not have form 'key=value' parsing " + match);
493             values[0] = values[0].toLowerCase(); // try to make this case insens
494             if (values[0].equals(STR_IN_PORT) || values[0].equals("input_port")) {
495                 this.inputPort = U16.t(Integer.valueOf(values[1]));
496                 inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
497                 match_len += 6;
498             } else if (values[0].equals(STR_DL_DST)
499                     || values[0].equals("eth_dst")) {
500                 this.dataLayerDestination = HexEncode
501                         .bytesFromHexString(values[1]);
502                 dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
503                 match_len += 10;
504             } else if (values[0].equals(STR_DL_SRC)
505                     || values[0].equals("eth_src")) {
506                 this.dataLayerSource = HexEncode.bytesFromHexString(values[1]);
507                 dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
508                 match_len += 10;
509                 this.wildcards &= ~OFPFW_DL_SRC;
510             } else if (values[0].equals(STR_DL_TYPE)
511                     || values[0].equals("eth_type")) {
512                 if (values[1].startsWith("0x"))
513                     this.dataLayerType = U16.t(Integer.valueOf(values[1]
514                             .replaceFirst("0x", ""), 16));
515                 else
516                     this.dataLayerType = U16.t(Integer.valueOf(values[1]));
517                 ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
518                 match_len += 6;
519             } else if (values[0].equals(STR_DL_VLAN)) {
520                 this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1]));
521                 dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
522                 match_len += 6;
523             } else if (values[0].equals(STR_DL_VLAN_PCP)) {
524                 this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short
525                         .valueOf(values[1]));
526                 this.wildcards &= ~OFPFW_DL_VLAN_PCP;
527             } else if (values[0].equals(STR_NW_DST)
528                     || values[0].equals("ip_dst")) {
529                 try {
530                     if (values[1].contains("/")) {
531                         String ipv6addr_wmask[] = values[1].split("/");
532                         this.nwDst = InetAddress.getByName(ipv6addr_wmask[0]);
533                         this.dstIPv6SubnetMaskbits = Short
534                                 .valueOf(ipv6addr_wmask[1]);
535                         nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
536                         match_len += 36;
537                     } else {
538                         this.nwDst = InetAddress.getByName(values[1]);
539                         nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
540                         match_len += 20;
541                     }
542                 } catch (UnknownHostException e) {
543                     logger.error("",e);
544                 }
545             } else if (values[0].equals(STR_NW_SRC)
546                     || values[0].equals("ip_src")) {
547                 try {
548                     if (values[1].contains("/")) {
549                         String ipv6addr_wmask[] = values[1].split("/");
550                         this.nwSrc = InetAddress.getByName(ipv6addr_wmask[0]);
551                         this.srcIPv6SubnetMaskbits = Short
552                                 .valueOf(ipv6addr_wmask[1]);
553                         nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
554                         match_len += 36;
555                     } else {
556                         this.nwSrc = InetAddress.getByName(values[1]);
557                         nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
558                         match_len += 20;
559                     }
560                 } catch (UnknownHostException e) {
561                     logger.error("",e);
562                 }
563             } else if (values[0].equals(STR_NW_PROTO)) {
564                 this.networkProtocol = U8.t(Short.valueOf(values[1]));
565                 if (!(this.networkProtocol == 0)) {
566                     /*
567                      * if user selects proto 0, don't use it
568                      */
569                     nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
570                     match_len += 5;
571                 }
572             } else if (values[0].equals(STR_NW_TOS)) {
573                 this.networkTypeOfService = U8.t(Short.valueOf(values[1]));
574                 nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
575                 match_len += 5;
576             } else if (values[0].equals(STR_TP_DST)) {
577                 this.transportDestination = U16.t(Integer.valueOf(values[1]));
578                 tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
579                 match_len += 6;
580             } else if (values[0].equals(STR_TP_SRC)) {
581                 this.transportSource = U16.t(Integer.valueOf(values[1]));
582                 tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
583                 match_len += 6;
584             } else
585                 throw new IllegalArgumentException("unknown token " + tokens[i]
586                         + " parsing " + match);
587         }
588
589         /*
590          * In a V6 extension message action list should be preceded by a padding of 0 to
591          * 7 bytes based upon following formula.
592          */
593
594         pad_size = (short) (((match_len + 7) / 8) * 8 - match_len);
595
596     }
597
598     /**
599      * Write this message's binary format to the specified ByteBuffer
600      *
601      * @param data
602      */
603     @Override
604     public void writeTo(ByteBuffer data) {
605         if (inputPortState == MatchFieldState.MATCH_FIELD_ONLY) {
606             byte[] ipv6ext_ingress_port_msg = getIPv6ExtensionPortMatchMsg(this.inputPort);
607             data.put(ipv6ext_ingress_port_msg);
608         }
609         if (ethTypeState == MatchFieldState.MATCH_FIELD_ONLY) {
610             byte[] ipv6ext_ether_type_msg = getIPv6ExtensionEtherTypeMatchMsg(this.dataLayerType);
611             data.put(ipv6ext_ether_type_msg);
612         }
613         if (dlDestState == MatchFieldState.MATCH_FIELD_ONLY) {
614             byte[] ipv6ext_destmac_msg = getIPv6ExtensionDestMacMatchMsg(this.dataLayerDestination);
615             data.put(ipv6ext_destmac_msg);
616         }
617         if (dlSourceState == MatchFieldState.MATCH_FIELD_ONLY) {
618             byte[] ipv6ext_srcmac_msg = getIPv6ExtensionSrcMacMatchMsg(this.dataLayerSource);
619             data.put(ipv6ext_srcmac_msg);
620         }
621         if (dlVlanState == MatchFieldState.MATCH_FIELD_ONLY) {
622             byte[] ipv6ext_vlan_id_msg = getIPv6ExtensionVlanIDMatchMsg(this.dataLayerVirtualLan);
623             data.put(ipv6ext_vlan_id_msg);
624         }
625         if (nwSrcState == MatchFieldState.MATCH_FIELD_ONLY) {
626             byte[] ipv6ext_src_ipv6_msg = getIPv6ExtensionSrcIPv6MatchMsg(this.nwSrc
627                     .getAddress());
628             data.put(ipv6ext_src_ipv6_msg);
629         } else if (nwSrcState == MatchFieldState.MATCH_FIELD_WITH_MASK) {
630             byte[] ipv6ext_src_ipv6_with_mask_msg = getIPv6ExtensionSrcIPv6MatchwithMaskMsg(
631                     this.nwSrc.getAddress(), this.srcIPv6SubnetMaskbits);
632             data.put(ipv6ext_src_ipv6_with_mask_msg);
633         }
634         if (nwDstState == MatchFieldState.MATCH_FIELD_ONLY) {
635             byte[] ipv6ext_dst_ipv6_msg = getIPv6ExtensionDstIPv6MatchMsg(this.nwDst
636                     .getAddress());
637             data.put(ipv6ext_dst_ipv6_msg);
638         } else if (nwDstState == MatchFieldState.MATCH_FIELD_WITH_MASK) {
639             byte[] ipv6ext_dst_ipv6_with_mask_msg = getIPv6ExtensionDstIPv6MatchwithMaskMsg(
640                     this.nwDst.getAddress(), this.dstIPv6SubnetMaskbits);
641             data.put(ipv6ext_dst_ipv6_with_mask_msg);
642         }
643         if (nwProtoState == MatchFieldState.MATCH_FIELD_ONLY) {
644             byte[] ipv6ext_protocol_msg = getIPv6ExtensionProtocolMatchMsg(this.networkProtocol);
645             if (ipv6ext_protocol_msg != null) {
646                 data.put(ipv6ext_protocol_msg);
647             }
648         }
649         if (nwTosState == MatchFieldState.MATCH_FIELD_ONLY) {
650             byte[] ipv6ext_tos_msg = getIPv6ExtensionTOSMatchMsg(this.networkTypeOfService);
651             data.put(ipv6ext_tos_msg);
652         }
653         if (tpSrcState == MatchFieldState.MATCH_FIELD_ONLY) {
654             byte[] ipv6ext_srcport_msg = null;
655             if (this.networkProtocol == IPProtocols.TCP.getValue()) {
656                 ipv6ext_srcport_msg = getIPv6ExtensionTCPSrcPortMatchMsg(this.transportSource);
657             } else if (this.networkProtocol == IPProtocols.UDP.getValue()) {
658                 ipv6ext_srcport_msg = getIPv6ExtensionUDPSrcPortMatchMsg(this.transportSource);
659             }
660             if (ipv6ext_srcport_msg != null) {
661                 data.put(ipv6ext_srcport_msg);
662             }
663         }
664         if (tpDstState == MatchFieldState.MATCH_FIELD_ONLY) {
665             byte[] ipv6ext_dstport_msg = null;
666             if (this.networkProtocol == IPProtocols.TCP.getValue()) {
667                 ipv6ext_dstport_msg = getIPv6ExtensionTCPDstPortMatchMsg(this.transportDestination);
668             } else if (this.networkProtocol == IPProtocols.UDP.getValue()) {
669                 ipv6ext_dstport_msg = getIPv6ExtensionUDPDstPortMatchMsg(this.transportDestination);
670             }
671             if (ipv6ext_dstport_msg != null) {
672                 data.put(ipv6ext_dstport_msg);
673             }
674         }
675         logger.trace("{}", this);
676     }
677
678     private void readInPort(ByteBuffer data, int nxmLen, boolean hasMask) {
679         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
680             /*
681              * mask is not allowed for inport port
682              */
683             return;
684         super.setInputPort(data.getShort());
685         this.inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
686         this.wildcards ^= (1 << 0); // Sync with 0F 1.0 Match
687         this.match_len += 6;
688     }
689
690     private void readDataLinkDestination(ByteBuffer data, int nxmLen,
691             boolean hasMask) {
692         if (hasMask) {
693             if ((nxmLen != 2 * 6) || (data.remaining() < 2 * 6))
694                 return;
695             else {
696                 byte[] bytes = new byte[6];
697                 data.get(bytes);
698                 super.setDataLayerDestination(bytes);
699                 this.dataLayerDestinationMask = new byte[6];
700                 data.get(this.dataLayerDestinationMask);
701                 this.dlDestState = MatchFieldState.MATCH_FIELD_WITH_MASK;
702                 this.match_len += 16;
703             }
704         } else {
705             if ((nxmLen != 6) || (data.remaining() < 6))
706                 return;
707             else {
708                 byte[] bytes = new byte[6];
709                 data.get(bytes);
710                 super.setDataLayerDestination(bytes);
711                 this.dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
712                 this.match_len += 10;
713             }
714         }
715         this.wildcards ^= (1 << 3); // Sync with 0F 1.0 Match
716     }
717
718     private void readDataLinkSource(ByteBuffer data, int nxmLen, boolean hasMask) {
719         /*
720          * mask is not allowed in data link source
721          */
722         if ((nxmLen != 6) || (data.remaining() < 6) || (hasMask))
723             return;
724         byte[] bytes = new byte[6];
725         data.get(bytes);
726         super.setDataLayerSource(bytes);
727         this.dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
728         this.match_len += 10;
729         this.wildcards ^= (1 << 2); // Sync with 0F 1.0 Match
730     }
731
732     private void readEtherType(ByteBuffer data, int nxmLen, boolean hasMask) {
733         /*
734          * mask is not allowed in ethertype
735          */
736         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
737             return;
738         super.setDataLayerType(data.getShort());
739         this.ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
740         this.wildcards ^= (1 << 4); // Sync with 0F 1.0 Match
741         this.match_len += 6;
742     }
743
744     private void readVlanTci(ByteBuffer data, int nxmLen, boolean hasMask) {
745         short vlan_mask = 0xfff;
746         if (hasMask) {
747             if ((nxmLen != 2 * 2) || (data.remaining() < 2 * 2))
748                 return;
749             else {
750                 short vlan = data.getShort();
751                 vlan &= vlan_mask;
752                 super.setDataLayerVirtualLan(vlan);
753                 this.dataLayerVirtualLanMask = data.getShort();
754                 this.dlVlanState = MatchFieldState.MATCH_FIELD_WITH_MASK;
755                 this.match_len += 8;
756                 this.wildcards ^= (1 << 20);
757             }
758         } else {
759             if ((nxmLen != 2) || (data.remaining() < 2))
760                 return;
761             else {
762                 short vlan = data.getShort();
763                 vlan &= vlan_mask;
764                 super.setDataLayerVirtualLan(vlan);
765                 this.dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
766                 this.match_len += 6;
767             }
768         }
769
770         this.wildcards ^= (1 << 1); // Sync with 0F 1.0 Match
771     }
772
773     private void readIpTos(ByteBuffer data, int nxmLen, boolean hasMask) {
774         /*
775          * mask is not allowed in IP TOS
776          */
777         if ((nxmLen != 1) || (data.remaining() < 1) || (hasMask))
778             return;
779         super.setNetworkTypeOfService(data.get());
780         this.nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
781         this.match_len += 5;
782         this.wildcards ^= (1 << 21); // Sync with 0F 1.0 Match
783     }
784
785     private void readIpProto(ByteBuffer data, int nxmLen, boolean hasMask) {
786         /*
787          * mask is not allowed in IP protocol
788          */
789         if ((nxmLen != 1) || (data.remaining() < 1) || (hasMask))
790             return;
791         super.setNetworkProtocol(data.get());
792         this.nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
793         this.match_len += 5;
794         this.wildcards ^= (1 << 5); // Sync with 0F 1.0 Match
795     }
796
797     private void readIpv4Src(ByteBuffer data, int nxmLen, boolean hasMask) {
798         if (hasMask) {
799             if ((nxmLen != 2 * 4) || (data.remaining() < 2 * 4))
800                 return;
801             else {
802                 byte[] sbytes = new byte[4];
803                 data.get(sbytes);
804                 try {
805                     this.nwSrc = InetAddress.getByAddress(sbytes);
806                 } catch (UnknownHostException e) {
807                     return;
808                 }
809                 byte[] mbytes = new byte[4];
810                 data.get(mbytes);
811                 try {
812                     this.networkSourceMask = InetAddress.getByAddress(mbytes);
813                 } catch (UnknownHostException e) {
814                     return;
815                 }
816                 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
817                 this.match_len += 12;
818                 int prefixlen = getNetworkMaskPrefixLength(mbytes);
819                 this.wildcards ^= (((1 << 6) - 1) << 8); // Sync with 0F 1.0 Match
820                 this.wildcards |= ((32 - prefixlen) << 8); // Sync with 0F 1.0 Match
821
822             }
823         } else {
824             if ((nxmLen != 4) || (data.remaining() < 4))
825                 return;
826             else {
827                 byte[] sbytes = new byte[4];
828                 data.get(sbytes);
829                 try {
830                     this.nwSrc = InetAddress.getByAddress(sbytes);
831                 } catch (UnknownHostException e) {
832                     return;
833                 }
834                 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
835                 this.match_len += 8;
836                 this.wildcards ^= (((1 << 6) - 1) << 8); // Sync with 0F 1.0 Match
837             }
838         }
839     }
840
841     private void readIpv4Dst(ByteBuffer data, int nxmLen, boolean hasMask) {
842         if (hasMask) {
843             if ((nxmLen != 2 * 4) || (data.remaining() < 2 * 4))
844                 return;
845             else {
846                 byte[] dbytes = new byte[4];
847                 data.get(dbytes);
848                 try {
849                     this.nwDst = InetAddress.getByAddress(dbytes);
850                 } catch (UnknownHostException e) {
851                     return;
852                 }
853                 byte[] mbytes = new byte[4];
854                 data.get(mbytes);
855                 try {
856                     this.networkDestinationMask = InetAddress
857                             .getByAddress(mbytes);
858                 } catch (UnknownHostException e) {
859                     return;
860                 }
861                 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
862                 this.match_len += 12;
863                 int prefixlen = getNetworkMaskPrefixLength(mbytes);
864                 this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0 Match
865                 this.wildcards |= ((32 - prefixlen) << 14); // Sync with 0F 1.0 Match
866             }
867         } else {
868             if ((nxmLen != 4) || (data.remaining() < 4))
869                 return;
870             else {
871                 byte[] dbytes = new byte[4];
872                 data.get(dbytes);
873                 try {
874                     this.nwDst = InetAddress.getByAddress(dbytes);
875                 } catch (UnknownHostException e) {
876                     return;
877                 }
878                 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
879                 this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0 Match
880                 this.match_len += 8;
881             }
882         }
883     }
884
885     private void readTcpSrc(ByteBuffer data, int nxmLen, boolean hasMask) {
886         /*
887          * mask is not allowed in TCP SRC
888          */
889         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
890             return;
891         super.setTransportSource(data.getShort());
892         this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
893         this.match_len += 6;
894         this.wildcards ^= (1 << 6); // Sync with 0F 1.0 Match
895     }
896
897     private void readTcpDst(ByteBuffer data, int nxmLen, boolean hasMask) {
898         /*
899          * mask is not allowed in TCP DST
900          */
901         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
902             return;
903         super.setTransportDestination(data.getShort());
904         this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
905         this.match_len += 6;
906         this.wildcards ^= (1 << 7); // Sync with 0F 1.0 Match
907     }
908
909     private void readUdpSrc(ByteBuffer data, int nxmLen, boolean hasMask) {
910         /*
911          * mask is not allowed in UDP SRC
912          */
913         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
914             return;
915         super.setTransportSource(data.getShort());
916         this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
917         this.match_len += 6;
918         this.wildcards ^= (1 << 6); // Sync with 0F 1.0 Match
919     }
920
921     private void readUdpDst(ByteBuffer data, int nxmLen, boolean hasMask) {
922         /*
923          * mask is not allowed in UDP DST
924          */
925         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
926             return;
927         super.setTransportDestination(data.getShort());
928         this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
929         this.match_len += 6;
930         this.wildcards ^= (1 << 7); // Sync with 0F 1.0 Match
931     }
932
933     private void readIpv6Src(ByteBuffer data, int nxmLen, boolean hasMask) {
934         if (hasMask) {
935             if ((nxmLen != 2 * 16) || (data.remaining() < 2 * 16))
936                 return;
937             else {
938                 byte[] sbytes = new byte[16];
939                 data.get(sbytes);
940                 try {
941                     this.nwSrc = InetAddress.getByAddress(sbytes);
942                 } catch (UnknownHostException e) {
943                     return;
944                 }
945                 byte[] mbytes = new byte[16];
946                 data.get(mbytes);
947                 try {
948                     this.networkSourceMask = InetAddress.getByAddress(mbytes);
949                 } catch (UnknownHostException e) {
950                     return;
951                 }
952                 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
953                 this.match_len += 36;
954             }
955         } else {
956             if ((nxmLen != 16) || (data.remaining() < 16))
957                 return;
958             else {
959                 byte[] sbytes = new byte[16];
960                 data.get(sbytes);
961                 try {
962                     this.nwSrc = InetAddress.getByAddress(sbytes);
963                 } catch (UnknownHostException e) {
964                     return;
965                 }
966                 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
967                 this.match_len += 20;
968             }
969         }
970     }
971
972     private void readIpv6Dst(ByteBuffer data, int nxmLen, boolean hasMask) {
973         if (hasMask) {
974             if ((nxmLen != 2 * 16) || (data.remaining() < 2 * 16))
975                 return;
976             else {
977                 byte[] dbytes = new byte[16];
978                 data.get(dbytes);
979                 try {
980                     this.nwDst = InetAddress.getByAddress(dbytes);
981                 } catch (UnknownHostException e) {
982                     return;
983                 }
984                 byte[] mbytes = new byte[16];
985                 data.get(mbytes);
986                 try {
987                     this.networkDestinationMask = InetAddress
988                             .getByAddress(mbytes);
989                 } catch (UnknownHostException e) {
990                     return;
991                 }
992                 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
993                 this.match_len += 36;
994             }
995         } else {
996             if ((nxmLen != 16) || (data.remaining() < 16))
997                 return;
998             else {
999                 byte[] dbytes = new byte[16];
1000                 data.get(dbytes);
1001                 try {
1002                     this.nwDst = InetAddress.getByAddress(dbytes);
1003                 } catch (UnknownHostException e) {
1004                     return;
1005                 }
1006                 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
1007                 this.match_len += 20;
1008             }
1009         }
1010     }
1011
1012     @Override
1013     public String toString() {
1014         return "V6Match [nwSrc=" + nwSrc + ", nwDst=" + nwDst
1015                 + ", inputPortMask=" + inputPortMask + ", dataLayerSourceMask="
1016                 + HexEncode.bytesToHexStringFormat(dataLayerSourceMask)
1017                 + ", dataLayerDestinationMask="
1018                 + HexEncode.bytesToHexStringFormat(dataLayerDestinationMask)
1019                 + ", dataLayerVirtualLanMask=" + dataLayerVirtualLanMask
1020                 + ", dataLayerVirtualLanPriorityCodePointMask="
1021                 + dataLayerVirtualLanPriorityCodePointMask
1022                 + ", dataLayerTypeMask=" + dataLayerTypeMask
1023                 + ", networkTypeOfServiceMask=" + networkTypeOfServiceMask
1024                 + ", networkProtocolMask=" + networkProtocolMask
1025                 + ", networkSourceMask=" + networkSourceMask
1026                 + ", networkDestinationMask=" + networkDestinationMask
1027                 + ", transportSourceMask=" + transportSourceMask
1028                 + ", transportDestinationMask=" + transportDestinationMask
1029                 + ", srcIPv6SubnetMaskbits=" + srcIPv6SubnetMaskbits
1030                 + ", dstIPv6SubnetMaskbits=" + dstIPv6SubnetMaskbits
1031                 + ", inputPortState=" + inputPortState + ", dlSourceState="
1032                 + dlSourceState + ", dlDestState=" + dlDestState
1033                 + ", dlVlanState=" + dlVlanState + ", ethTypeState="
1034                 + ethTypeState + ", nwTosState=" + nwTosState
1035                 + ", nwProtoState=" + nwProtoState + ", nwSrcState="
1036                 + nwSrcState + ", nwDstState=" + nwDstState + ", tpSrcState="
1037                 + tpSrcState + ", tpDstState=" + tpDstState + ", match_len="
1038                 + match_len + ", pad_size=" + pad_size + "]";
1039     }
1040
1041     /**
1042      * Read the data corresponding to the match field (received from the wire)
1043      * Input: data: match field(s). Since match field is of variable length, the whole data that are passed in
1044      * are assumed to fem0tbd.be the match fields.
1045      * @param data
1046      */
1047     @Override
1048     public void readFrom(ByteBuffer data) {
1049         readFromInternal(data);
1050         postprocessWildCardInfo();
1051     }
1052
1053     private void readFromInternal(ByteBuffer data) {
1054         this.match_len = 0;
1055         while (data.remaining() > 0) {
1056             if (data.remaining() < 4) {
1057                 /*
1058                  * at least 4 bytes for each match header
1059                  */
1060                 logger.error("Invalid Vendor Extension Header. Size {}", data
1061                         .remaining());
1062                 return;
1063             }
1064             /*
1065              * read the 4 byte match header
1066              */
1067             int nxmVendor = data.getShort();
1068             int b = data.get();
1069             int nxmField = b >> 1;
1070             boolean hasMask = ((b & 0x01) == 1) ? true : false;
1071             int nxmLen = data.get();
1072             if (nxmVendor == Extension_Types.OF_10.getValue()) {
1073                 if (nxmField == OF_Match_Types.MATCH_OF_IN_PORT.getValue()) {
1074                     readInPort(data, nxmLen, hasMask);
1075                 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_DST
1076                         .getValue()) {
1077                     readDataLinkDestination(data, nxmLen, hasMask);
1078                 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_SRC
1079                         .getValue()) {
1080                     readDataLinkSource(data, nxmLen, hasMask);
1081                 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_TYPE
1082                         .getValue()) {
1083                     readEtherType(data, nxmLen, hasMask);
1084                 } else if (nxmField == OF_Match_Types.MATCH_OF_VLAN_TCI
1085                         .getValue()) {
1086                     readVlanTci(data, nxmLen, hasMask);
1087                 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_TOS
1088                         .getValue()) {
1089                     readIpTos(data, nxmLen, hasMask);
1090                 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_PROTO
1091                         .getValue()) {
1092                     readIpProto(data, nxmLen, hasMask);
1093                 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_SRC
1094                         .getValue()) {
1095                     readIpv4Src(data, nxmLen, hasMask);
1096                 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_DST
1097                         .getValue()) {
1098                     readIpv4Dst(data, nxmLen, hasMask);
1099                 } else if (nxmField == OF_Match_Types.MATCH_OF_TCP_SRC
1100                         .getValue()) {
1101                     readTcpSrc(data, nxmLen, hasMask);
1102                 } else if (nxmField == OF_Match_Types.MATCH_OF_TCP_DST
1103                         .getValue()) {
1104                     readTcpDst(data, nxmLen, hasMask);
1105                 } else if (nxmField == OF_Match_Types.MATCH_OF_UDP_SRC
1106                         .getValue()) {
1107                     readUdpSrc(data, nxmLen, hasMask);
1108                 } else if (nxmField == OF_Match_Types.MATCH_OF_UDP_DST
1109                         .getValue()) {
1110                     readUdpDst(data, nxmLen, hasMask);
1111                 } else {
1112                     // unexpected nxmField
1113                     return;
1114                 }
1115             } else if (nxmVendor == Extension_Types.IPV6EXT.getValue()) {
1116                 if (nxmField == IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_SRC
1117                         .getValue()) {
1118                     readIpv6Src(data, nxmLen, hasMask);
1119                 } else if (nxmField == IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_DST
1120                         .getValue()) {
1121                     readIpv6Dst(data, nxmLen, hasMask);
1122                 } else {
1123                     // unexpected nxmField
1124                     return;
1125                 }
1126             } else {
1127                 // invalid nxmVendor
1128                 return;
1129             }
1130         }
1131     }
1132
1133     private void postprocessWildCardInfo() {
1134         // Sync with 0F 1.0 Match
1135         if (super.getDataLayerType() == 0x800) {
1136             if (((this.wildcards >> 8) & 0x3f) == 0x3f) {
1137                 //ipv4 src processing
1138                 this.wildcards ^= (((1 << 5) - 1) << 8);
1139             }
1140             if (((this.wildcards >> 14) & 0x3f) == 0x3f) {
1141                 //ipv4 dest processing
1142                 this.wildcards ^= (((1 << 5) - 1) << 14);
1143             }
1144         } else {
1145             this.wildcards = 0;
1146         }
1147     }
1148
1149     @Override
1150     public V6Match clone() {
1151
1152         V6Match ret = (V6Match) super.clone();
1153         try {
1154             if (this.nwSrc != null) {
1155                 ret.nwSrc = InetAddress.getByAddress(this.nwSrc.getAddress());
1156             }
1157             if (this.nwDst != null) {
1158                 ret.nwDst = InetAddress.getByAddress(this.nwDst.getAddress());
1159             }
1160             return ret;
1161         } catch (UnknownHostException e) {
1162             throw new RuntimeException(e);
1163         }
1164     }
1165
1166     /**
1167      * Get nw_dst
1168      *
1169      * @return
1170      */
1171
1172     public InetAddress getNetworkDest() {
1173         return this.nwDst;
1174     }
1175
1176     /**
1177      * Get nw_src
1178      *
1179      * @return
1180      */
1181
1182     public void setNetworkSrc(InetAddress address) {
1183         nwSrc = address;
1184     }
1185
1186     /**
1187      * Set nw_dst
1188      *
1189      * @return
1190      */
1191
1192     public void setNetworkDest(InetAddress address) {
1193         nwDst = address;
1194     }
1195
1196     /**
1197      * Set nw_src
1198      *
1199      * @return
1200      */
1201
1202     public InetAddress getNetworkSrc() {
1203         return this.nwSrc;
1204     }
1205
1206     private int getNetworkMaskPrefixLength(byte[] netMask) {
1207         ByteBuffer nm = ByteBuffer.wrap(netMask);
1208         int trailingZeros = Integer.numberOfTrailingZeros(nm.getInt());
1209         return 32 - trailingZeros;
1210     }
1211
1212     public short getInputPortMask() {
1213         return inputPortMask;
1214     }
1215
1216     public void setInputPort(short port, short mask) {
1217         super.inputPort = port;
1218         this.inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
1219         match_len += 6;
1220         // Looks like mask is not allowed for input port. Will discard it
1221     }
1222
1223     public byte[] getDataLayerSourceMask() {
1224         return dataLayerSourceMask;
1225     }
1226
1227     public void setDataLayerSource(byte[] mac, byte[] mask) {
1228         if (mac != null) {
1229             System.arraycopy(mac, 0, super.dataLayerSource, 0, mac.length);
1230         }
1231         if (mask == null) {
1232             this.dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
1233             this.match_len += 10;
1234         } else {
1235             if (this.dataLayerSourceMask == null) {
1236                 this.dataLayerSourceMask = new byte[mask.length];
1237             }
1238             System.arraycopy(mask, 0, this.dataLayerSourceMask, 0, mask.length);
1239             this.dlSourceState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1240             this.match_len += 16;
1241         }
1242     }
1243
1244     public byte[] getDataLayerDestinationMask() {
1245         return dataLayerDestinationMask;
1246     }
1247
1248     public void setDataLayerDestination(byte[] mac, byte[] mask) {
1249         if (mac != null) {
1250             System.arraycopy(mac, 0, super.dataLayerDestination, 0, mac.length);
1251         }
1252         if (mask == null) {
1253             this.dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
1254             this.match_len += 10;
1255         } else {
1256             if (this.dataLayerDestinationMask == null) {
1257                 this.dataLayerDestinationMask = new byte[mask.length];
1258             }
1259             System.arraycopy(mask, 0, this.dataLayerDestinationMask, 0,
1260                     mask.length);
1261             this.dlDestState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1262             this.match_len += 16;
1263         }
1264     }
1265
1266     public short getDataLayerVirtualLanMask() {
1267         return dataLayerVirtualLanMask;
1268     }
1269
1270     public void setDataLayerVirtualLan(short vlan, short mask) {
1271         super.dataLayerVirtualLan = vlan;
1272         if (mask == 0) {
1273             this.dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
1274             this.match_len += 6;
1275         } else {
1276             this.dataLayerVirtualLanMask = mask;
1277             this.dlVlanState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1278             this.match_len += 8;
1279         }
1280     }
1281
1282     public void setDataLayerVirtualLanPriorityCodePoint(byte pcp, byte mask) {
1283         super.dataLayerVirtualLanPriorityCodePoint = pcp;
1284     }
1285
1286     public void setDataLayerType(short ethType, short mask) {
1287         // mask not allowed
1288         super.dataLayerType = ethType;
1289         this.ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
1290         this.match_len += 6;
1291     }
1292
1293     public void setNetworkTypeOfService(byte tos, byte mask) {
1294         // mask not allowed
1295         super.networkTypeOfService = tos;
1296         this.nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
1297         match_len += 5;
1298     }
1299
1300     public void setNetworkProtocol(byte ipProto, byte mask) {
1301         // mask not allowed
1302         super.networkProtocol = ipProto;
1303         this.nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
1304         this.match_len += 5;
1305     }
1306
1307     public InetAddress getNetworkSourceMask() {
1308         return networkSourceMask;
1309     }
1310
1311     public void setNetworkSource(InetAddress address, InetAddress mask) {
1312         this.nwSrc = address;
1313         if (mask == null) {
1314             this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1315             this.match_len += (address instanceof Inet6Address) ? 20 : 8;
1316         } else {
1317             this.networkSourceMask = mask;
1318             this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1319             this.match_len += (address instanceof Inet6Address) ? 36 : 12;
1320         }
1321     }
1322
1323     public InetAddress getNetworkDestinationMask() {
1324         return networkDestinationMask;
1325     }
1326
1327     public void setNetworkDestination(InetAddress address, InetAddress mask) {
1328         this.nwDst = address;
1329         if (mask == null) {
1330             this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
1331             this.match_len += (address instanceof Inet6Address) ? 20 : 8;
1332         } else {
1333             this.networkDestinationMask = mask;
1334             this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1335             this.match_len += (address instanceof Inet6Address) ? 36 : 12;
1336         }
1337     }
1338
1339     public void setTransportSource(short tpSrc, short mask) {
1340         // mask not allowed
1341         super.transportSource = tpSrc;
1342         this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1343         this.match_len += 6;
1344     }
1345
1346     public short getTransportDestinationMask() {
1347         return transportDestinationMask;
1348     }
1349
1350     public void setTransportDestination(short tpDst, short mask) {
1351         // mask not allowed
1352         super.transportDestination = tpDst;
1353         this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
1354         this.match_len += 6;
1355     }
1356
1357     private byte[] getIPv6NetworkMaskinBytes(short num) {
1358         byte[] nbytes = new byte[16];
1359         int quot = num / 8;
1360         int bits = num % 8;
1361         int i;
1362
1363         for (i = 0; i < quot; i++) {
1364             nbytes[i] = (byte) 0xff;
1365         }
1366
1367         if (bits > 0) {
1368             nbytes[i] = (byte) 0xff;
1369             nbytes[i] <<= 8 - bits;
1370         }
1371         return nbytes;
1372     }
1373 }