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