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