Merge "Increase timeout for waiting for broker service in sal-binding-it."
[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.getWildcards() & OFMatch.OFPFW_DL_VLAN_PCP) == 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                     this.wildcards ^= (1 << 1); // Sync with 0F 1.0 Match
843                 }
844                 if ((this.dataLayerVirtualLanTCIMask & 0xe000) != 0) {
845                     // else if its a vlan pcp mask
846                     // extract the vlan pcp
847                     super.setDataLayerVirtualLanPriorityCodePoint(getVlanPCP(firstByte));
848                     this.wildcards ^= (1 << 20);
849                 }
850                 this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
851                 this.match_len += 8;
852             }
853         } else {
854             if ((nxmLen != 2) || (data.remaining() < 2)) {
855                 return;
856             }
857             else {
858                 // get the vlan pcp
859                 byte firstByte = data.get();
860                 byte secondByte = data.get();
861                 super.setDataLayerVirtualLanPriorityCodePoint(getVlanPCP(firstByte));
862                 super.setDataLayerVirtualLan(getVlanID(firstByte, secondByte));
863                 this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
864                 this.match_len += 6;
865                 this.wildcards ^= (1 << 1); // Sync with 0F 1.0 Match
866                 this.wildcards ^= (1 << 20);
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         }
1220     }
1221
1222     @Override
1223     public V6Match clone() {
1224
1225         V6Match ret = (V6Match) super.clone();
1226         try {
1227             if (this.nwSrc != null) {
1228                 ret.nwSrc = (Inet6Address) InetAddress.getByAddress(this.nwSrc.getAddress());
1229             }
1230             if (this.nwDst != null) {
1231                 ret.nwDst = (Inet6Address) InetAddress.getByAddress(this.nwDst.getAddress());
1232             }
1233             return ret;
1234         } catch (UnknownHostException e) {
1235             throw new RuntimeException(e);
1236         }
1237     }
1238
1239     /**
1240      * Get nw_dst
1241      *
1242      * @return
1243      */
1244
1245     public Inet6Address getNetworkDest() {
1246         return this.nwDst;
1247     }
1248
1249     /**
1250      * Set nw_src
1251      *
1252      * @return
1253      */
1254
1255     public Inet6Address getNetworkSrc() {
1256         return this.nwSrc;
1257     }
1258
1259     private int getNetworkMaskPrefixLength(byte[] netMask) {
1260         ByteBuffer nm = ByteBuffer.wrap(netMask);
1261         int trailingZeros = Integer.numberOfTrailingZeros(nm.getInt());
1262         return 32 - trailingZeros;
1263     }
1264
1265     public short getInputPortMask() {
1266         return inputPortMask;
1267     }
1268
1269     public void setInputPort(short port, short mask) {
1270         super.inputPort = port;
1271         this.inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
1272         match_len += 6;
1273         // Looks like mask is not allowed for input port. Will discard it
1274     }
1275
1276     public byte[] getDataLayerSourceMask() {
1277         return dataLayerSourceMask;
1278     }
1279
1280     public void setDataLayerSource(byte[] mac, byte[] mask) {
1281         if (mac != null) {
1282             System.arraycopy(mac, 0, super.dataLayerSource, 0, mac.length);
1283         }
1284         if (mask == null) {
1285             this.dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
1286             this.match_len += 10;
1287         } else {
1288             if (this.dataLayerSourceMask == null) {
1289                 this.dataLayerSourceMask = new byte[mask.length];
1290             }
1291             System.arraycopy(mask, 0, this.dataLayerSourceMask, 0, mask.length);
1292             this.dlSourceState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1293             this.match_len += 16;
1294         }
1295     }
1296
1297     public byte[] getDataLayerDestinationMask() {
1298         return dataLayerDestinationMask;
1299     }
1300
1301     public void setDataLayerDestination(byte[] mac, byte[] mask) {
1302         if (mac != null) {
1303             System.arraycopy(mac, 0, super.dataLayerDestination, 0, mac.length);
1304         }
1305         if (mask == null) {
1306             this.dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
1307             this.match_len += 10;
1308         } else {
1309             if (this.dataLayerDestinationMask == null) {
1310                 this.dataLayerDestinationMask = new byte[mask.length];
1311             }
1312             System.arraycopy(mask, 0, this.dataLayerDestinationMask, 0,
1313                     mask.length);
1314             this.dlDestState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1315             this.match_len += 16;
1316         }
1317     }
1318
1319     public void setDataLayerVirtualLan(short vlan, short mask) {
1320         // mask is ignored as the code sets the appropriate mask
1321         super.dataLayerVirtualLan = vlan;
1322         this.dlVlanIDState = MatchFieldState.MATCH_FIELD_ONLY;
1323         // the variable dlVlanIDState is not really used as a flag
1324         // for serializing and deserializing. Rather it is used as a flag
1325         // to check if the vlan id is being set so that we can set the
1326         // dlVlanTCIState appropriately.
1327         if (this.dlVlanPCPState != MatchFieldState.MATCH_ABSENT) {
1328             this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
1329             match_len -= 2;
1330         } else {
1331             this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1332             this.dataLayerVirtualLanTCIMask = 0x1fff;
1333             match_len += 8;
1334         }
1335     }
1336
1337     public void setDataLayerVirtualLanPriorityCodePoint(byte pcp, byte mask) {
1338         // mask is ignored as the code sets the appropriate mask
1339         super.dataLayerVirtualLanPriorityCodePoint = pcp;
1340         this.dlVlanPCPState = MatchFieldState.MATCH_FIELD_ONLY;
1341         // the variable dlVlanPCPState is not really used as a flag
1342         // for serializing and deserializing. Rather it is used as a flag
1343         // to check if the vlan pcp is being set so that we can set the
1344         // dlVlanTCIState appropriately.
1345         if (this.dlVlanIDState != MatchFieldState.MATCH_ABSENT) {
1346             this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_ONLY;
1347             match_len -= 2;
1348         } else {
1349             this.dlVlanTCIState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1350             this.dataLayerVirtualLanTCIMask = 0xf000;
1351             match_len += 8;
1352         }
1353     }
1354
1355     public void setDataLayerType(short ethType, short mask) {
1356         // mask not allowed
1357         super.dataLayerType = ethType;
1358         this.ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
1359         this.match_len += 6;
1360     }
1361
1362     public void setNetworkTypeOfService(byte tos, byte mask) {
1363         // mask not allowed
1364         super.networkTypeOfService = tos;
1365         this.nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
1366         match_len += 5;
1367     }
1368
1369     public void setNetworkProtocol(byte ipProto, byte mask) {
1370         // mask not allowed
1371         super.networkProtocol = ipProto;
1372         this.nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
1373         this.match_len += 5;
1374     }
1375
1376     public Inet6Address getNetworkSourceMask() {
1377         return (this.nwSrcState == MatchFieldState.MATCH_FIELD_WITH_MASK) ? (Inet6Address) NetUtils.getInetNetworkMask(
1378                 this.srcIPv6SubnetMaskbits, true) : null;
1379     }
1380
1381     public void setNetworkSource(InetAddress address, InetAddress mask) {
1382         if (address instanceof Inet6Address) {
1383             this.nwSrc = (Inet6Address) address;
1384             if (mask == null) {
1385                 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1386                 this.match_len += (address instanceof Inet6Address) ? 20 : 8;
1387             } else {
1388                 this.srcIPv6SubnetMaskbits = (short)NetUtils.getSubnetMaskLength(mask);
1389                 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1390                 this.match_len += (address instanceof Inet6Address) ? 36 : 12;
1391             }
1392         } else {
1393             super.setNetworkSource(NetUtils.byteArray4ToInt(address.getAddress()));
1394             this.wildcards ^= (((1 << 6) - 1) << 8);
1395             if (mask == null) {
1396                 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1397                 this.match_len += 8;
1398             } else {
1399                 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1400                 this.match_len += 12;
1401                 this.wildcards |= ((32 - NetUtils.getSubnetMaskLength(mask)) << 8);
1402             }
1403         }
1404     }
1405
1406     public Inet6Address getNetworkDestinationMask() {
1407         return (this.nwDstState == MatchFieldState.MATCH_FIELD_WITH_MASK) ? (Inet6Address) NetUtils.getInetNetworkMask(
1408                 this.dstIPv6SubnetMaskbits, true) : null;
1409     }
1410
1411     public void setNetworkDestination(InetAddress address, InetAddress mask) {
1412         if (address instanceof Inet6Address) {
1413             this.nwDst = (Inet6Address) address;
1414             if (mask == null) {
1415                 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
1416                 this.match_len += (address instanceof Inet6Address) ? 20 : 8;
1417             } else {
1418                 this.dstIPv6SubnetMaskbits = (short)NetUtils.getSubnetMaskLength(mask);
1419                 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1420                 this.match_len += (address instanceof Inet6Address) ? 36 : 12;
1421             }
1422         } else {
1423             this.setNetworkDestination(NetUtils.byteArray4ToInt(address.getAddress()));
1424             this.wildcards ^= (((1 << 6) - 1) << 14);
1425             if (mask == null) {
1426                 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
1427                 this.match_len += 8;
1428             } else {
1429                 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1430                 this.match_len += 12;
1431                 this.wildcards |= ((32 - NetUtils.getSubnetMaskLength(mask)) << 14);
1432             }
1433         }
1434     }
1435
1436     public void setTransportSource(short tpSrc, short mask) {
1437         // mask not allowed
1438         super.transportSource = tpSrc;
1439         this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1440         this.match_len += 6;
1441     }
1442
1443     public short getTransportDestinationMask() {
1444         return transportDestinationMask;
1445     }
1446
1447     public void setTransportDestination(short tpDst, short mask) {
1448         // mask not allowed
1449         super.transportDestination = tpDst;
1450         this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
1451         this.match_len += 6;
1452     }
1453
1454     private byte[] getIPv6NetworkMaskinBytes(short num) {
1455         byte[] nbytes = new byte[16];
1456         int quot = num / 8;
1457         int bits = num % 8;
1458         int i;
1459
1460         for (i = 0; i < quot; i++) {
1461             nbytes[i] = (byte) 0xff;
1462         }
1463
1464         if (bits > 0) {
1465             nbytes[i] = (byte) 0xff;
1466             nbytes[i] <<= 8 - bits;
1467         }
1468         return nbytes;
1469     }
1470
1471     @Override
1472     public int hashCode() {
1473         final int prime = 31;
1474         int result = super.hashCode();
1475         result = prime * result + Arrays.hashCode(dataLayerDestinationMask);
1476         result = prime * result + Arrays.hashCode(dataLayerSourceMask);
1477         result = prime * result + dataLayerTypeMask;
1478         result = prime * result + dataLayerVirtualLanTCIMask;
1479         result = prime * result
1480                 + ((dlDestState == null) ? 0 : dlDestState.hashCode());
1481         result = prime * result
1482                 + ((dlSourceState == null) ? 0 : dlSourceState.hashCode());
1483         result = prime * result
1484                 + ((dlVlanTCIState == null) ? 0 : dlVlanTCIState.hashCode());
1485         result = prime * result + dstIPv6SubnetMaskbits;
1486         result = prime * result
1487                 + ((ethTypeState == null) ? 0 : ethTypeState.hashCode());
1488         result = prime * result + inputPortMask;
1489         result = prime * result
1490                 + ((inputPortState == null) ? 0 : inputPortState.hashCode());
1491         result = prime * result + match_len;
1492         result = prime * result + networkProtocolMask;
1493         result = prime * result + networkTypeOfServiceMask;
1494         result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
1495         result = prime * result
1496                 + ((nwDstState == null) ? 0 : nwDstState.hashCode());
1497         result = prime * result
1498                 + ((nwProtoState == null) ? 0 : nwProtoState.hashCode());
1499         result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
1500         result = prime * result
1501                 + ((nwSrcState == null) ? 0 : nwSrcState.hashCode());
1502         result = prime * result
1503                 + ((nwTosState == null) ? 0 : nwTosState.hashCode());
1504         result = prime * result + pad_size;
1505         result = prime * result + srcIPv6SubnetMaskbits;
1506         result = prime * result
1507                 + ((tpDstState == null) ? 0 : tpDstState.hashCode());
1508         result = prime * result
1509                 + ((tpSrcState == null) ? 0 : tpSrcState.hashCode());
1510         result = prime * result + transportDestinationMask;
1511         result = prime * result + transportSourceMask;
1512         return result;
1513     }
1514
1515     @Override
1516     public boolean equals(Object obj) {
1517         if (this == obj) {
1518             return true;
1519         }
1520         if (!super.equals(obj)) {
1521             return false;
1522         }
1523         if (getClass() != obj.getClass()) {
1524             return false;
1525         }
1526         V6Match other = (V6Match) obj;
1527         if (!Arrays.equals(dataLayerDestinationMask, other.dataLayerDestinationMask)) {
1528             return false;
1529         }
1530         if (!Arrays.equals(dataLayerSourceMask, other.dataLayerSourceMask)) {
1531             return false;
1532         }
1533         if (dataLayerTypeMask != other.dataLayerTypeMask) {
1534             return false;
1535         }
1536         if (dataLayerVirtualLanTCIMask != other.dataLayerVirtualLanTCIMask) {
1537             return false;
1538         }
1539         if (dlVlanTCIState != other.dlVlanTCIState) {
1540             return false;
1541         }
1542         if (dlSourceState != other.dlSourceState) {
1543             return false;
1544         }
1545         if (dstIPv6SubnetMaskbits != other.dstIPv6SubnetMaskbits) {
1546             return false;
1547         }
1548         if (ethTypeState != other.ethTypeState) {
1549             return false;
1550         }
1551         if (inputPortMask != other.inputPortMask) {
1552             return false;
1553         }
1554         if (inputPortState != other.inputPortState) {
1555             return false;
1556         }
1557         if (match_len != other.match_len) {
1558             return false;
1559         }
1560         if (networkProtocolMask != other.networkProtocolMask) {
1561             return false;
1562         }
1563         if (networkTypeOfServiceMask != other.networkTypeOfServiceMask) {
1564             return false;
1565         }
1566         if (nwDst == null) {
1567             if (other.nwDst != null) {
1568                 return false;
1569             }
1570         } else if (!nwDst.equals(other.nwDst)) {
1571             return false;
1572         }
1573         if (nwDstState != other.nwDstState) {
1574             return false;
1575         }
1576         if (nwProtoState != other.nwProtoState) {
1577             return false;
1578         }
1579         if (nwSrc == null) {
1580             if (other.nwSrc != null) {
1581                 return false;
1582             }
1583         } else if (!nwSrc.equals(other.nwSrc)) {
1584             return false;
1585         }
1586         if (nwSrcState != other.nwSrcState) {
1587             return false;
1588         }
1589         if (nwTosState != other.nwTosState) {
1590             return false;
1591         }
1592         if (pad_size != other.pad_size) {
1593             return false;
1594         }
1595         if (srcIPv6SubnetMaskbits != other.srcIPv6SubnetMaskbits) {
1596             return false;
1597         }
1598         if (tpDstState != other.tpDstState) {
1599             return false;
1600         }
1601         if (tpSrcState != other.tpSrcState) {
1602             return false;
1603         }
1604         if (transportDestinationMask != other.transportDestinationMask) {
1605             return false;
1606         }
1607         if (transportSourceMask != other.transportSourceMask) {
1608             return false;
1609         }
1610         return true;
1611     }
1612 }