Revert "Checkstyle enforcer"
[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 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     @Override
606     public void writeTo(ByteBuffer data) {
607         if (inputPortState == MatchFieldState.MATCH_FIELD_ONLY) {
608             byte[] ipv6ext_ingress_port_msg = getIPv6ExtensionPortMatchMsg(this.inputPort);
609             data.put(ipv6ext_ingress_port_msg);
610         }
611         if (ethTypeState == MatchFieldState.MATCH_FIELD_ONLY) {
612             byte[] ipv6ext_ether_type_msg = getIPv6ExtensionEtherTypeMatchMsg(this.dataLayerType);
613             data.put(ipv6ext_ether_type_msg);
614         }
615         if (dlDestState == MatchFieldState.MATCH_FIELD_ONLY) {
616             byte[] ipv6ext_destmac_msg = getIPv6ExtensionDestMacMatchMsg(this.dataLayerDestination);
617             data.put(ipv6ext_destmac_msg);
618         }
619         if (dlSourceState == MatchFieldState.MATCH_FIELD_ONLY) {
620             byte[] ipv6ext_srcmac_msg = getIPv6ExtensionSrcMacMatchMsg(this.dataLayerSource);
621             data.put(ipv6ext_srcmac_msg);
622         }
623         if (dlVlanState == MatchFieldState.MATCH_FIELD_ONLY) {
624             byte[] ipv6ext_vlan_id_msg = getIPv6ExtensionVlanIDMatchMsg(this.dataLayerVirtualLan);
625             data.put(ipv6ext_vlan_id_msg);
626         }
627         if (nwSrcState == MatchFieldState.MATCH_FIELD_ONLY) {
628             byte[] ipv6ext_src_ipv6_msg = getIPv6ExtensionSrcIPv6MatchMsg(this.nwSrc
629                     .getAddress());
630             data.put(ipv6ext_src_ipv6_msg);
631         } else if (nwSrcState == MatchFieldState.MATCH_FIELD_WITH_MASK) {
632             byte[] ipv6ext_src_ipv6_with_mask_msg = getIPv6ExtensionSrcIPv6MatchwithMaskMsg(
633                     this.nwSrc.getAddress(), this.srcIPv6SubnetMaskbits);
634             data.put(ipv6ext_src_ipv6_with_mask_msg);
635         }
636         if (nwDstState == MatchFieldState.MATCH_FIELD_ONLY) {
637             byte[] ipv6ext_dst_ipv6_msg = getIPv6ExtensionDstIPv6MatchMsg(this.nwDst
638                     .getAddress());
639             data.put(ipv6ext_dst_ipv6_msg);
640         } else if (nwDstState == MatchFieldState.MATCH_FIELD_WITH_MASK) {
641             byte[] ipv6ext_dst_ipv6_with_mask_msg = getIPv6ExtensionDstIPv6MatchwithMaskMsg(
642                     this.nwDst.getAddress(), this.dstIPv6SubnetMaskbits);
643             data.put(ipv6ext_dst_ipv6_with_mask_msg);
644         }
645         if (nwProtoState == MatchFieldState.MATCH_FIELD_ONLY) {
646             byte[] ipv6ext_protocol_msg = getIPv6ExtensionProtocolMatchMsg(this.networkProtocol);
647             if (ipv6ext_protocol_msg != null) {
648                 data.put(ipv6ext_protocol_msg);
649             }
650         }
651         if (nwTosState == MatchFieldState.MATCH_FIELD_ONLY) {
652             byte[] ipv6ext_tos_msg = getIPv6ExtensionTOSMatchMsg(this.networkTypeOfService);
653             data.put(ipv6ext_tos_msg);
654         }
655         if (tpSrcState == MatchFieldState.MATCH_FIELD_ONLY) {
656             byte[] ipv6ext_srcport_msg = null;
657             if (this.networkProtocol == IPProtocols.TCP.getValue()) {
658                 ipv6ext_srcport_msg = getIPv6ExtensionTCPSrcPortMatchMsg(this.transportSource);
659             } else if (this.networkProtocol == IPProtocols.UDP.getValue()) {
660                 ipv6ext_srcport_msg = getIPv6ExtensionUDPSrcPortMatchMsg(this.transportSource);
661             }
662             if (ipv6ext_srcport_msg != null) {
663                 data.put(ipv6ext_srcport_msg);
664             }
665         }
666         if (tpDstState == MatchFieldState.MATCH_FIELD_ONLY) {
667             byte[] ipv6ext_dstport_msg = null;
668             if (this.networkProtocol == IPProtocols.TCP.getValue()) {
669                 ipv6ext_dstport_msg = getIPv6ExtensionTCPDstPortMatchMsg(this.transportDestination);
670             } else if (this.networkProtocol == IPProtocols.UDP.getValue()) {
671                 ipv6ext_dstport_msg = getIPv6ExtensionUDPDstPortMatchMsg(this.transportDestination);
672             }
673             if (ipv6ext_dstport_msg != null) {
674                 data.put(ipv6ext_dstport_msg);
675             }
676         }
677         logger.trace("{}", this);
678     }
679
680     private void readInPort(ByteBuffer data, int nxmLen, boolean hasMask) {
681         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
682             /*
683              * mask is not allowed for inport port
684              */
685             return;
686         super.setInputPort(data.getShort());
687         this.inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
688         this.wildcards ^= (1 << 0); // Sync with 0F 1.0 Match
689         this.match_len += 6;
690     }
691
692     private void readDataLinkDestination(ByteBuffer data, int nxmLen,
693             boolean hasMask) {
694         if (hasMask) {
695             if ((nxmLen != 2 * 6) || (data.remaining() < 2 * 6))
696                 return;
697             else {
698                 byte[] bytes = new byte[6];
699                 data.get(bytes);
700                 super.setDataLayerDestination(bytes);
701                 this.dataLayerDestinationMask = new byte[6];
702                 data.get(this.dataLayerDestinationMask);
703                 this.dlDestState = MatchFieldState.MATCH_FIELD_WITH_MASK;
704                 this.match_len += 16;
705             }
706         } else {
707             if ((nxmLen != 6) || (data.remaining() < 6))
708                 return;
709             else {
710                 byte[] bytes = new byte[6];
711                 data.get(bytes);
712                 super.setDataLayerDestination(bytes);
713                 this.dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
714                 this.match_len += 10;
715             }
716         }
717         this.wildcards ^= (1 << 3); // Sync with 0F 1.0 Match
718     }
719
720     private void readDataLinkSource(ByteBuffer data, int nxmLen, boolean hasMask) {
721         /*
722          * mask is not allowed in data link source
723          */
724         if ((nxmLen != 6) || (data.remaining() < 6) || (hasMask))
725             return;
726         byte[] bytes = new byte[6];
727         data.get(bytes);
728         super.setDataLayerSource(bytes);
729         this.dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
730         this.match_len += 10;
731         this.wildcards ^= (1 << 2); // Sync with 0F 1.0 Match
732     }
733
734     private void readEtherType(ByteBuffer data, int nxmLen, boolean hasMask) {
735         /*
736          * mask is not allowed in ethertype
737          */
738         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
739             return;
740         super.setDataLayerType(data.getShort());
741         this.ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
742         this.wildcards ^= (1 << 4); // Sync with 0F 1.0 Match
743         this.match_len += 6;
744     }
745
746     private void readVlanTci(ByteBuffer data, int nxmLen, boolean hasMask) {
747         short vlan_mask = 0xfff;
748         if (hasMask) {
749             if ((nxmLen != 2 * 2) || (data.remaining() < 2 * 2))
750                 return;
751             else {
752                 short vlan = data.getShort();
753                 vlan &= vlan_mask;
754                 super.setDataLayerVirtualLan(vlan);
755                 this.dataLayerVirtualLanMask = data.getShort();
756                 this.dlVlanState = MatchFieldState.MATCH_FIELD_WITH_MASK;
757                 this.match_len += 8;
758                 this.wildcards ^= (1 << 20);
759             }
760         } else {
761             if ((nxmLen != 2) || (data.remaining() < 2))
762                 return;
763             else {
764                 short vlan = data.getShort();
765                 vlan &= vlan_mask;
766                 super.setDataLayerVirtualLan(vlan);
767                 this.dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
768                 this.match_len += 6;
769             }
770         }
771
772         this.wildcards ^= (1 << 1); // Sync with 0F 1.0 Match
773     }
774
775     private void readIpTos(ByteBuffer data, int nxmLen, boolean hasMask) {
776         /*
777          * mask is not allowed in IP TOS
778          */
779         if ((nxmLen != 1) || (data.remaining() < 1) || (hasMask))
780             return;
781         super.setNetworkTypeOfService(data.get());
782         this.nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
783         this.match_len += 5;
784         this.wildcards ^= (1 << 21); // Sync with 0F 1.0 Match
785     }
786
787     private void readIpProto(ByteBuffer data, int nxmLen, boolean hasMask) {
788         /*
789          * mask is not allowed in IP protocol
790          */
791         if ((nxmLen != 1) || (data.remaining() < 1) || (hasMask))
792             return;
793         super.setNetworkProtocol(data.get());
794         this.nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
795         this.match_len += 5;
796         this.wildcards ^= (1 << 5); // Sync with 0F 1.0 Match
797     }
798
799     private void readIpv4Src(ByteBuffer data, int nxmLen, boolean hasMask) {
800         if (hasMask) {
801             if ((nxmLen != 2 * 4) || (data.remaining() < 2 * 4))
802                 return;
803             else {
804                 byte[] sbytes = new byte[4];
805                 data.get(sbytes);
806                 try {
807                     this.nwSrc = InetAddress.getByAddress(sbytes);
808                 } catch (UnknownHostException e) {
809                     return;
810                 }
811                 byte[] mbytes = new byte[4];
812                 data.get(mbytes);
813                 try {
814                     this.networkSourceMask = InetAddress.getByAddress(mbytes);
815                 } catch (UnknownHostException e) {
816                     return;
817                 }
818                 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
819                 this.match_len += 12;
820                 int prefixlen = getNetworkMaskPrefixLength(mbytes);
821                 this.wildcards ^= (((1 << 6) - 1) << 8); // Sync with 0F 1.0 Match
822                 this.wildcards |= ((32 - prefixlen) << 8); // Sync with 0F 1.0 Match
823
824             }
825         } else {
826             if ((nxmLen != 4) || (data.remaining() < 4))
827                 return;
828             else {
829                 byte[] sbytes = new byte[4];
830                 data.get(sbytes);
831                 try {
832                     this.nwSrc = InetAddress.getByAddress(sbytes);
833                 } catch (UnknownHostException e) {
834                     return;
835                 }
836                 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
837                 this.match_len += 8;
838                 this.wildcards ^= (((1 << 6) - 1) << 8); // Sync with 0F 1.0 Match
839             }
840         }
841     }
842
843     private void readIpv4Dst(ByteBuffer data, int nxmLen, boolean hasMask) {
844         if (hasMask) {
845             if ((nxmLen != 2 * 4) || (data.remaining() < 2 * 4))
846                 return;
847             else {
848                 byte[] dbytes = new byte[4];
849                 data.get(dbytes);
850                 try {
851                     this.nwDst = InetAddress.getByAddress(dbytes);
852                 } catch (UnknownHostException e) {
853                     return;
854                 }
855                 byte[] mbytes = new byte[4];
856                 data.get(mbytes);
857                 try {
858                     this.networkDestinationMask = InetAddress
859                             .getByAddress(mbytes);
860                 } catch (UnknownHostException e) {
861                     return;
862                 }
863                 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
864                 this.match_len += 12;
865                 int prefixlen = getNetworkMaskPrefixLength(mbytes);
866                 this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0 Match
867                 this.wildcards |= ((32 - prefixlen) << 14); // Sync with 0F 1.0 Match
868             }
869         } else {
870             if ((nxmLen != 4) || (data.remaining() < 4))
871                 return;
872             else {
873                 byte[] dbytes = new byte[4];
874                 data.get(dbytes);
875                 try {
876                     this.nwDst = InetAddress.getByAddress(dbytes);
877                 } catch (UnknownHostException e) {
878                     return;
879                 }
880                 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
881                 this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0 Match
882                 this.match_len += 8;
883             }
884         }
885     }
886
887     private void readTcpSrc(ByteBuffer data, int nxmLen, boolean hasMask) {
888         /*
889          * mask is not allowed in TCP SRC
890          */
891         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
892             return;
893         super.setTransportSource(data.getShort());
894         this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
895         this.match_len += 6;
896         this.wildcards ^= (1 << 6); // Sync with 0F 1.0 Match
897     }
898
899     private void readTcpDst(ByteBuffer data, int nxmLen, boolean hasMask) {
900         /*
901          * mask is not allowed in TCP DST
902          */
903         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
904             return;
905         super.setTransportDestination(data.getShort());
906         this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
907         this.match_len += 6;
908         this.wildcards ^= (1 << 7); // Sync with 0F 1.0 Match
909     }
910
911     private void readUdpSrc(ByteBuffer data, int nxmLen, boolean hasMask) {
912         /*
913          * mask is not allowed in UDP SRC
914          */
915         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
916             return;
917         super.setTransportSource(data.getShort());
918         this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
919         this.match_len += 6;
920         this.wildcards ^= (1 << 6); // Sync with 0F 1.0 Match
921     }
922
923     private void readUdpDst(ByteBuffer data, int nxmLen, boolean hasMask) {
924         /*
925          * mask is not allowed in UDP DST
926          */
927         if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
928             return;
929         super.setTransportDestination(data.getShort());
930         this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
931         this.match_len += 6;
932         this.wildcards ^= (1 << 7); // Sync with 0F 1.0 Match
933     }
934
935     private void readIpv6Src(ByteBuffer data, int nxmLen, boolean hasMask) {
936         if (hasMask) {
937             if ((nxmLen != 2 * 16) || (data.remaining() < 2 * 16))
938                 return;
939             else {
940                 byte[] sbytes = new byte[16];
941                 data.get(sbytes);
942                 try {
943                     this.nwSrc = InetAddress.getByAddress(sbytes);
944                 } catch (UnknownHostException e) {
945                     return;
946                 }
947                 byte[] mbytes = new byte[16];
948                 data.get(mbytes);
949                 try {
950                     this.networkSourceMask = InetAddress.getByAddress(mbytes);
951                 } catch (UnknownHostException e) {
952                     return;
953                 }
954                 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
955                 this.match_len += 36;
956             }
957         } else {
958             if ((nxmLen != 16) || (data.remaining() < 16))
959                 return;
960             else {
961                 byte[] sbytes = new byte[16];
962                 data.get(sbytes);
963                 try {
964                     this.nwSrc = InetAddress.getByAddress(sbytes);
965                 } catch (UnknownHostException e) {
966                     return;
967                 }
968                 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
969                 this.match_len += 20;
970             }
971         }
972     }
973
974     private void readIpv6Dst(ByteBuffer data, int nxmLen, boolean hasMask) {
975         if (hasMask) {
976             if ((nxmLen != 2 * 16) || (data.remaining() < 2 * 16))
977                 return;
978             else {
979                 byte[] dbytes = new byte[16];
980                 data.get(dbytes);
981                 try {
982                     this.nwDst = InetAddress.getByAddress(dbytes);
983                 } catch (UnknownHostException e) {
984                     return;
985                 }
986                 byte[] mbytes = new byte[16];
987                 data.get(mbytes);
988                 try {
989                     this.networkDestinationMask = InetAddress
990                             .getByAddress(mbytes);
991                 } catch (UnknownHostException e) {
992                     return;
993                 }
994                 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
995                 this.match_len += 36;
996             }
997         } else {
998             if ((nxmLen != 16) || (data.remaining() < 16))
999                 return;
1000             else {
1001                 byte[] dbytes = new byte[16];
1002                 data.get(dbytes);
1003                 try {
1004                     this.nwDst = InetAddress.getByAddress(dbytes);
1005                 } catch (UnknownHostException e) {
1006                     return;
1007                 }
1008                 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
1009                 this.match_len += 20;
1010             }
1011         }
1012     }
1013
1014     @Override
1015     public String toString() {
1016         return "V6Match[" + ReflectionToStringBuilder.toString(this) + "]";
1017     }
1018
1019     /**
1020      * Read the data corresponding to the match field (received from the wire)
1021      * Input: data: match field(s). Since match field is of variable length, the whole data that are passed in
1022      * are assumed to fem0tbd.be the match fields.
1023      * @param data
1024      */
1025     @Override
1026     public void readFrom(ByteBuffer data) {
1027         readFromInternal(data);
1028         postprocessWildCardInfo();
1029     }
1030
1031     private void readFromInternal(ByteBuffer data) {
1032         this.match_len = 0;
1033         while (data.remaining() > 0) {
1034             if (data.remaining() < 4) {
1035                 /*
1036                  * at least 4 bytes for each match header
1037                  */
1038                 logger.error("Invalid Vendor Extension Header. Size {}", data
1039                         .remaining());
1040                 return;
1041             }
1042             /*
1043              * read the 4 byte match header
1044              */
1045             int nxmVendor = data.getShort();
1046             int b = data.get();
1047             int nxmField = b >> 1;
1048             boolean hasMask = ((b & 0x01) == 1) ? true : false;
1049             int nxmLen = data.get();
1050             if (nxmVendor == Extension_Types.OF_10.getValue()) {
1051                 if (nxmField == OF_Match_Types.MATCH_OF_IN_PORT.getValue()) {
1052                     readInPort(data, nxmLen, hasMask);
1053                 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_DST
1054                         .getValue()) {
1055                     readDataLinkDestination(data, nxmLen, hasMask);
1056                 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_SRC
1057                         .getValue()) {
1058                     readDataLinkSource(data, nxmLen, hasMask);
1059                 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_TYPE
1060                         .getValue()) {
1061                     readEtherType(data, nxmLen, hasMask);
1062                 } else if (nxmField == OF_Match_Types.MATCH_OF_VLAN_TCI
1063                         .getValue()) {
1064                     readVlanTci(data, nxmLen, hasMask);
1065                 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_TOS
1066                         .getValue()) {
1067                     readIpTos(data, nxmLen, hasMask);
1068                 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_PROTO
1069                         .getValue()) {
1070                     readIpProto(data, nxmLen, hasMask);
1071                 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_SRC
1072                         .getValue()) {
1073                     readIpv4Src(data, nxmLen, hasMask);
1074                 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_DST
1075                         .getValue()) {
1076                     readIpv4Dst(data, nxmLen, hasMask);
1077                 } else if (nxmField == OF_Match_Types.MATCH_OF_TCP_SRC
1078                         .getValue()) {
1079                     readTcpSrc(data, nxmLen, hasMask);
1080                 } else if (nxmField == OF_Match_Types.MATCH_OF_TCP_DST
1081                         .getValue()) {
1082                     readTcpDst(data, nxmLen, hasMask);
1083                 } else if (nxmField == OF_Match_Types.MATCH_OF_UDP_SRC
1084                         .getValue()) {
1085                     readUdpSrc(data, nxmLen, hasMask);
1086                 } else if (nxmField == OF_Match_Types.MATCH_OF_UDP_DST
1087                         .getValue()) {
1088                     readUdpDst(data, nxmLen, hasMask);
1089                 } else {
1090                     // unexpected nxmField
1091                     return;
1092                 }
1093             } else if (nxmVendor == Extension_Types.IPV6EXT.getValue()) {
1094                 if (nxmField == IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_SRC
1095                         .getValue()) {
1096                     readIpv6Src(data, nxmLen, hasMask);
1097                 } else if (nxmField == IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_DST
1098                         .getValue()) {
1099                     readIpv6Dst(data, nxmLen, hasMask);
1100                 } else {
1101                     // unexpected nxmField
1102                     return;
1103                 }
1104             } else {
1105                 // invalid nxmVendor
1106                 return;
1107             }
1108         }
1109     }
1110
1111     private void postprocessWildCardInfo() {
1112         // Sync with 0F 1.0 Match
1113         if (super.getDataLayerType() == 0x800) {
1114             if (((this.wildcards >> 8) & 0x3f) == 0x3f) {
1115                 //ipv4 src processing
1116                 this.wildcards ^= (((1 << 5) - 1) << 8);
1117             }
1118             if (((this.wildcards >> 14) & 0x3f) == 0x3f) {
1119                 //ipv4 dest processing
1120                 this.wildcards ^= (((1 << 5) - 1) << 14);
1121             }
1122         } else {
1123             this.wildcards = 0;
1124         }
1125     }
1126
1127     @Override
1128     public V6Match clone() {
1129
1130         V6Match ret = (V6Match) super.clone();
1131         try {
1132             if (this.nwSrc != null) {
1133                 ret.nwSrc = InetAddress.getByAddress(this.nwSrc.getAddress());
1134             }
1135             if (this.nwDst != null) {
1136                 ret.nwDst = InetAddress.getByAddress(this.nwDst.getAddress());
1137             }
1138             return ret;
1139         } catch (UnknownHostException e) {
1140             throw new RuntimeException(e);
1141         }
1142     }
1143
1144     /**
1145      * Get nw_dst
1146      *
1147      * @return
1148      */
1149
1150     public InetAddress getNetworkDest() {
1151         return this.nwDst;
1152     }
1153
1154     /**
1155      * Get nw_src
1156      *
1157      * @return
1158      */
1159
1160     public void setNetworkSrc(InetAddress address) {
1161         nwSrc = address;
1162     }
1163
1164     /**
1165      * Set nw_dst
1166      *
1167      * @return
1168      */
1169
1170     public void setNetworkDest(InetAddress address) {
1171         nwDst = address;
1172     }
1173
1174     /**
1175      * Set nw_src
1176      *
1177      * @return
1178      */
1179
1180     public InetAddress getNetworkSrc() {
1181         return this.nwSrc;
1182     }
1183
1184     private int getNetworkMaskPrefixLength(byte[] netMask) {
1185         ByteBuffer nm = ByteBuffer.wrap(netMask);
1186         int trailingZeros = Integer.numberOfTrailingZeros(nm.getInt());
1187         return 32 - trailingZeros;
1188     }
1189
1190     public short getInputPortMask() {
1191         return inputPortMask;
1192     }
1193
1194     public void setInputPort(short port, short mask) {
1195         super.inputPort = port;
1196         this.inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
1197         match_len += 6;
1198         // Looks like mask is not allowed for input port. Will discard it
1199     }
1200
1201     public byte[] getDataLayerSourceMask() {
1202         return dataLayerSourceMask;
1203     }
1204
1205     public void setDataLayerSource(byte[] mac, byte[] mask) {
1206         if (mac != null) {
1207             System.arraycopy(mac, 0, super.dataLayerSource, 0, mac.length);
1208         }
1209         if (mask == null) {
1210             this.dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
1211             this.match_len += 10;
1212         } else {
1213             if (this.dataLayerSourceMask == null) {
1214                 this.dataLayerSourceMask = new byte[mask.length];
1215             }
1216             System.arraycopy(mask, 0, this.dataLayerSourceMask, 0, mask.length);
1217             this.dlSourceState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1218             this.match_len += 16;
1219         }
1220     }
1221
1222     public byte[] getDataLayerDestinationMask() {
1223         return dataLayerDestinationMask;
1224     }
1225
1226     public void setDataLayerDestination(byte[] mac, byte[] mask) {
1227         if (mac != null) {
1228             System.arraycopy(mac, 0, super.dataLayerDestination, 0, mac.length);
1229         }
1230         if (mask == null) {
1231             this.dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
1232             this.match_len += 10;
1233         } else {
1234             if (this.dataLayerDestinationMask == null) {
1235                 this.dataLayerDestinationMask = new byte[mask.length];
1236             }
1237             System.arraycopy(mask, 0, this.dataLayerDestinationMask, 0,
1238                     mask.length);
1239             this.dlDestState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1240             this.match_len += 16;
1241         }
1242     }
1243
1244     public short getDataLayerVirtualLanMask() {
1245         return dataLayerVirtualLanMask;
1246     }
1247
1248     public void setDataLayerVirtualLan(short vlan, short mask) {
1249         super.dataLayerVirtualLan = vlan;
1250         if (mask == 0) {
1251             this.dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
1252             this.match_len += 6;
1253         } else {
1254             this.dataLayerVirtualLanMask = mask;
1255             this.dlVlanState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1256             this.match_len += 8;
1257         }
1258     }
1259
1260     public void setDataLayerVirtualLanPriorityCodePoint(byte pcp, byte mask) {
1261         super.dataLayerVirtualLanPriorityCodePoint = pcp;
1262     }
1263
1264     public void setDataLayerType(short ethType, short mask) {
1265         // mask not allowed
1266         super.dataLayerType = ethType;
1267         this.ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
1268         this.match_len += 6;
1269     }
1270
1271     public void setNetworkTypeOfService(byte tos, byte mask) {
1272         // mask not allowed
1273         super.networkTypeOfService = tos;
1274         this.nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
1275         match_len += 5;
1276     }
1277
1278     public void setNetworkProtocol(byte ipProto, byte mask) {
1279         // mask not allowed
1280         super.networkProtocol = ipProto;
1281         this.nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
1282         this.match_len += 5;
1283     }
1284
1285     public InetAddress getNetworkSourceMask() {
1286         return networkSourceMask;
1287     }
1288
1289     public void setNetworkSource(InetAddress address, InetAddress mask) {
1290         this.nwSrc = address;
1291         if (mask == null) {
1292             this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1293             this.match_len += (address instanceof Inet6Address) ? 20 : 8;
1294         } else {
1295             this.networkSourceMask = mask;
1296             this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1297             this.match_len += (address instanceof Inet6Address) ? 36 : 12;
1298         }
1299     }
1300
1301     public InetAddress getNetworkDestinationMask() {
1302         return networkDestinationMask;
1303     }
1304
1305     public void setNetworkDestination(InetAddress address, InetAddress mask) {
1306         this.nwDst = address;
1307         if (mask == null) {
1308             this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
1309             this.match_len += (address instanceof Inet6Address) ? 20 : 8;
1310         } else {
1311             this.networkDestinationMask = mask;
1312             this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1313             this.match_len += (address instanceof Inet6Address) ? 36 : 12;
1314         }
1315     }
1316
1317     public void setTransportSource(short tpSrc, short mask) {
1318         // mask not allowed
1319         super.transportSource = tpSrc;
1320         this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1321         this.match_len += 6;
1322     }
1323
1324     public short getTransportDestinationMask() {
1325         return transportDestinationMask;
1326     }
1327
1328     public void setTransportDestination(short tpDst, short mask) {
1329         // mask not allowed
1330         super.transportDestination = tpDst;
1331         this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
1332         this.match_len += 6;
1333     }
1334
1335     private byte[] getIPv6NetworkMaskinBytes(short num) {
1336         byte[] nbytes = new byte[16];
1337         int quot = num / 8;
1338         int bits = num % 8;
1339         int i;
1340
1341         for (i = 0; i < quot; i++) {
1342             nbytes[i] = (byte) 0xff;
1343         }
1344
1345         if (bits > 0) {
1346             nbytes[i] = (byte) 0xff;
1347             nbytes[i] <<= 8 - bits;
1348         }
1349         return nbytes;
1350     }
1351 }