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