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