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