3 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
10 package org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension;
12 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
13 import org.openflow.protocol.OFMatch;
14 import org.openflow.util.U16;
15 import org.openflow.util.U8;
17 import java.net.Inet6Address;
18 import org.opendaylight.controller.sal.utils.HexEncode;
20 import java.net.InetAddress;
21 import java.net.UnknownHostException;
22 import java.nio.ByteBuffer;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * This Class forms the vendor specific IPv6 Flow Match messages as well as
29 * processes the vendor specific IPv6 Stats Reply message.
31 * For message creation, it parses the user entered IPv6 match fields, creates
32 * a sub-message for each field which are later used to form the complete
35 * For message processing, it parses the incoming message and reads each field
36 * of the message and stores in appropriate field of V6Match object.
40 public class V6Match extends OFMatch implements Cloneable {
41 private static final Logger logger = LoggerFactory.getLogger(V6Match.class);
42 private static final long serialVersionUID = 1L;
43 protected InetAddress nwSrc;
44 protected InetAddress nwDst;
45 protected short inputPortMask;
46 protected byte[] dataLayerSourceMask;
47 protected byte[] dataLayerDestinationMask;
48 protected short dataLayerVirtualLanMask;
49 protected byte dataLayerVirtualLanPriorityCodePointMask;
50 protected short dataLayerTypeMask;
51 protected byte networkTypeOfServiceMask;
52 protected byte networkProtocolMask;
53 protected InetAddress networkSourceMask;
54 protected InetAddress networkDestinationMask;
55 protected short transportSourceMask;
56 protected short transportDestinationMask;
57 protected short srcIPv6SubnetMaskbits;
58 protected short dstIPv6SubnetMaskbits;
60 protected MatchFieldState inputPortState;
61 protected MatchFieldState dlSourceState;
62 protected MatchFieldState dlDestState;
63 protected MatchFieldState dlVlanState;
64 protected MatchFieldState ethTypeState;
65 protected MatchFieldState nwTosState;
66 protected MatchFieldState nwProtoState;
67 protected MatchFieldState nwSrcState;
68 protected MatchFieldState nwDstState;
69 protected MatchFieldState tpSrcState;
70 protected MatchFieldState tpDstState;
71 protected short match_len = 0;
72 protected short pad_size = 0;
74 private static int IPV6_EXT_MIN_HDR_LEN = 36;
76 private enum MatchFieldState {
77 MATCH_ABSENT, MATCH_FIELD_ONLY, MATCH_FIELD_WITH_MASK
80 private enum OF_Match_Types {
81 MATCH_OF_IN_PORT(0), MATCH_OF_ETH_DST(1), MATCH_OF_ETH_SRC(2), MATCH_OF_ETH_TYPE(
82 3), MATCH_OF_VLAN_TCI(4), MATCH_OF_IP_TOS(5), MATCH_OF_IP_PROTO(
83 6), MATCH_OF_IP_SRC(7), MATCH_OF_IP_DST(8), MATCH_OF_TCP_SRC(9), MATCH_OF_TCP_DST(
84 10), MATCH_OF_UDP_SRC(11), MATCH_OF_UDP_DST(12), MATCH_OF_ICMTP_TYPE(
85 13), MATCH_OF_ICMP_CODE(14), MATCH_OF_ARP_OP(15);
89 private OF_Match_Types(int value) {
93 public int getValue() {
98 private enum IPv6Extension_Match_Types {
99 MATCH_IPV6EXT_TUN_ID(16), MATCH_IPV6EXT_ARP_SHA(17), MATCH_IPV6EXT_ARP_THA(
100 18), MATCH_IPV6EXT_IPV6_SRC(19), MATCH_IPV6EXT_IPV6_DST(20);
104 private IPv6Extension_Match_Types(int value) {
108 public int getValue() {
113 public enum Extension_Types {
114 OF_10(0), IPV6EXT(1);
118 private Extension_Types(int value) {
122 public int getValue() {
133 this.inputPortMask = 0;
134 this.dataLayerSourceMask = null;
135 this.dataLayerDestinationMask = null;
136 this.dataLayerTypeMask = 0;
137 this.dataLayerVirtualLanMask = 0;
138 this.dataLayerVirtualLanPriorityCodePointMask = 0;
139 this.networkDestinationMask = null;
140 this.networkSourceMask = null;
141 this.networkTypeOfServiceMask = 0;
142 this.networkProtocolMask = 0;
143 this.transportSourceMask = 0;
144 this.transportDestinationMask = 0;
146 this.inputPortState = MatchFieldState.MATCH_ABSENT;
147 this.dlSourceState = MatchFieldState.MATCH_ABSENT;
148 this.dlDestState = MatchFieldState.MATCH_ABSENT;
149 this.dlVlanState = MatchFieldState.MATCH_ABSENT;
150 this.ethTypeState = MatchFieldState.MATCH_ABSENT;
151 this.nwTosState = MatchFieldState.MATCH_ABSENT;
152 this.nwProtoState = MatchFieldState.MATCH_ABSENT;
153 this.nwSrcState = MatchFieldState.MATCH_ABSENT;
154 this.nwDstState = MatchFieldState.MATCH_ABSENT;
155 this.tpSrcState = MatchFieldState.MATCH_ABSENT;
156 this.tpDstState = MatchFieldState.MATCH_ABSENT;
162 public V6Match(OFMatch match) {
167 this.networkSourceMask = null;
168 if (match.getNetworkSource() != 0) {
169 InetAddress address = null;
171 address = InetAddress.getByAddress(ByteBuffer.allocate(4)
172 .putInt(match.getNetworkSource()).array());
173 } catch (UnknownHostException e) {
176 this.setNetworkSource(address, null);
179 this.nwSrcState = MatchFieldState.MATCH_ABSENT;
182 this.networkDestinationMask = null;
183 if (match.getNetworkDestination() != 0) {
184 InetAddress address = null;
186 address = InetAddress.getByAddress(ByteBuffer.allocate(4)
187 .putInt(match.getNetworkDestination()).array());
188 } catch (UnknownHostException e) {
191 this.setNetworkDestination(address, null);
194 this.nwDstState = MatchFieldState.MATCH_ABSENT;
197 this.inputPortMask = 0;
198 if (match.getInputPort() != 0) {
199 this.setInputPort(match.getInputPort(), (short) 0);
201 this.inputPortMask = 0;
202 this.inputPortState = MatchFieldState.MATCH_ABSENT;
205 this.dataLayerSourceMask = null;
206 if (match.getDataLayerSource() != null) {
207 this.setDataLayerSource(match.getDataLayerSource(), null);
209 this.dataLayerSource = null;
210 this.dlSourceState = MatchFieldState.MATCH_ABSENT;
212 this.dataLayerDestinationMask = null;
213 if (match.getDataLayerDestination() != null) {
214 this.setDataLayerDestination(match.getDataLayerDestination(), null);
216 this.dataLayerDestination = null;
217 this.dlDestState = MatchFieldState.MATCH_ABSENT;
220 this.dataLayerTypeMask = 0;
221 if (match.getDataLayerType() != 0) {
222 this.setDataLayerType(match.getDataLayerType(), (short) 0);
224 this.dataLayerType = 0;
225 this.ethTypeState = MatchFieldState.MATCH_ABSENT;
228 this.dataLayerVirtualLanMask = 0;
229 if (match.getDataLayerVirtualLan() != 0) {
230 this.setDataLayerVirtualLan(match.getDataLayerVirtualLan(),
233 this.dataLayerVirtualLan = 0;
234 this.dlVlanState = MatchFieldState.MATCH_ABSENT;
237 this.dataLayerVirtualLanPriorityCodePointMask = 0;
238 if (match.getDataLayerVirtualLanPriorityCodePoint() != 0) {
239 this.setDataLayerVirtualLanPriorityCodePoint(match
240 .getDataLayerVirtualLanPriorityCodePoint(), (byte) 0);
242 this.dataLayerVirtualLanPriorityCodePoint = 0;
245 this.networkProtocolMask = 0;
246 if (match.getNetworkProtocol() != 0) {
247 this.setNetworkProtocol(this.networkProtocol = match
248 .getNetworkProtocol(), (byte) 0);
250 this.networkProtocol = 0;
251 this.nwProtoState = MatchFieldState.MATCH_ABSENT;
254 this.networkTypeOfServiceMask = 0;
255 if (match.getNetworkTypeOfService() != 0) {
256 this.setNetworkTypeOfService(this.networkTypeOfService = match
257 .getNetworkTypeOfService(), (byte) 0);
259 this.networkTypeOfService = match.getNetworkTypeOfService();
260 this.nwTosState = MatchFieldState.MATCH_ABSENT;
263 this.transportSourceMask = 0;
264 if (match.getTransportSource() != 0) {
265 this.setTransportSource(match.getTransportSource(), (short) 0);
267 this.transportSource = 0;
268 this.tpSrcState = MatchFieldState.MATCH_ABSENT;
271 this.transportDestinationMask = 0;
272 if (match.getTransportDestination() != 0) {
273 this.setTransportDestination(match.getTransportDestination(),
276 this.transportDestination = 0;
277 this.tpDstState = MatchFieldState.MATCH_ABSENT;
280 this.setWildcards(match.getWildcards());
283 private enum IPProtocols {
284 ICMP(1), TCP(6), UDP(17), ICMPV6(58);
286 private int protocol;
288 private IPProtocols(int value) {
289 this.protocol = value;
292 private byte getValue() {
293 return (byte) this.protocol;
297 public short getIPv6MatchLen() {
301 public int getIPv6ExtMinHdrLen() {
302 return IPV6_EXT_MIN_HDR_LEN;
305 public short getPadSize() {
306 return (short) (((match_len + 7) / 8) * 8 - match_len);
309 private int getIPv6ExtensionMatchHeader(Extension_Types extType, int field,
310 int has_mask, int length) {
311 return (((extType.getValue() & 0x0000ffff) << 16)
312 | ((field & 0x0000007f) << 9) | ((has_mask & 0x00000001) << 8) | (length & 0x000000ff));
315 private byte[] getIPv6ExtensionPortMatchMsg(short port) {
316 ByteBuffer ipv6ext_port_msg = ByteBuffer.allocate(6);
317 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
318 OF_Match_Types.MATCH_OF_IN_PORT.getValue(), 0, 2);
319 ipv6ext_port_msg.putInt(nxm_header);
320 ipv6ext_port_msg.putShort(port);
321 return (ipv6ext_port_msg.array());
324 private byte[] getIPv6ExtensionDestMacMatchMsg(byte[] destMac) {
325 ByteBuffer ipv6ext_destmac_msg = ByteBuffer.allocate(10);
326 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
327 OF_Match_Types.MATCH_OF_ETH_DST.getValue(), 0, 6);
328 ipv6ext_destmac_msg.putInt(nxm_header);
329 ipv6ext_destmac_msg.put(destMac);
330 return (ipv6ext_destmac_msg.array());
333 private byte[] getIPv6ExtensionSrcMacMatchMsg(byte[] srcMac) {
334 ByteBuffer ipv6ext_srcmac_msg = ByteBuffer.allocate(10);
335 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
336 OF_Match_Types.MATCH_OF_ETH_SRC.getValue(), 0, 6);
337 ipv6ext_srcmac_msg.putInt(nxm_header);
338 ipv6ext_srcmac_msg.put(srcMac);
339 return (ipv6ext_srcmac_msg.array());
342 private byte[] getIPv6ExtensionEtherTypeMatchMsg(short EtherType) {
343 ByteBuffer ipv6ext_etype_msg = ByteBuffer.allocate(6);
344 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
345 OF_Match_Types.MATCH_OF_ETH_TYPE.getValue(), 0, 2);
346 ipv6ext_etype_msg.putInt(nxm_header);
347 ipv6ext_etype_msg.putShort(EtherType);
348 return (ipv6ext_etype_msg.array());
351 private byte[] getIPv6ExtensionVlanIDMatchMsg(short VLAN) {
352 ByteBuffer ipv6ext_vlanid_msg = ByteBuffer.allocate(6);
353 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
354 OF_Match_Types.MATCH_OF_VLAN_TCI.getValue(), 0, 2);
355 ipv6ext_vlanid_msg.putInt(nxm_header);
356 ipv6ext_vlanid_msg.putShort(VLAN);
357 return (ipv6ext_vlanid_msg.array());
360 private byte[] getIPv6ExtensionSrcIPv6MatchMsg(byte[] srcIpv6) {
361 ByteBuffer ipv6ext_ipv6_msg = ByteBuffer.allocate(20);
362 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.IPV6EXT,
363 IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_SRC.getValue(), 0,
365 ipv6ext_ipv6_msg.putInt(nxm_header);
366 ipv6ext_ipv6_msg.put(srcIpv6);
367 return (ipv6ext_ipv6_msg.array());
370 private byte[] getIPv6ExtensionSrcIPv6MatchwithMaskMsg(byte[] srcIpv6,
372 ByteBuffer ipv6ext_ipv6_msg = ByteBuffer.allocate(36);
373 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.IPV6EXT,
374 IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_SRC.getValue(), 1,
376 ipv6ext_ipv6_msg.putInt(nxm_header);
377 ipv6ext_ipv6_msg.put(srcIpv6);
378 byte[] ipv6_mask = getIPv6NetworkMaskinBytes(masklen);
379 ipv6ext_ipv6_msg.put(ipv6_mask);
380 return (ipv6ext_ipv6_msg.array());
383 private byte[] getIPv6ExtensionDstIPv6MatchMsg(byte[] dstIpv6) {
384 ByteBuffer ipv6ext_ipv6_msg = ByteBuffer.allocate(20);
385 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.IPV6EXT,
386 IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_DST.getValue(), 0,
388 ipv6ext_ipv6_msg.putInt(nxm_header);
389 ipv6ext_ipv6_msg.put(dstIpv6);
390 return (ipv6ext_ipv6_msg.array());
393 private byte[] getIPv6ExtensionDstIPv6MatchwithMaskMsg(byte[] dstIpv6,
395 ByteBuffer ipv6ext_ipv6_msg = ByteBuffer.allocate(36);
396 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.IPV6EXT,
397 IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_DST.getValue(), 1,
399 ipv6ext_ipv6_msg.putInt(nxm_header);
400 ipv6ext_ipv6_msg.put(dstIpv6);
401 byte[] ipv6_mask = getIPv6NetworkMaskinBytes(masklen);
402 ipv6ext_ipv6_msg.put(ipv6_mask);
403 return (ipv6ext_ipv6_msg.array());
406 private byte[] getIPv6ExtensionProtocolMatchMsg(byte protocol) {
407 ByteBuffer ipv6ext_proto_msg = ByteBuffer.allocate(5);
408 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
409 OF_Match_Types.MATCH_OF_IP_PROTO.getValue(), 0, 1);
413 ipv6ext_proto_msg.putInt(nxm_header);
414 if (protocol == IPProtocols.ICMP.getValue()) {
416 * The front end passes the same protocol type values for IPv4
417 * and IPv6 flows. For the Protocol types we allow in our GUI
418 * (ICMP, TCP, UDP), ICMP is the only one which is different for
419 * IPv6. It is 1 for v4 and 58 for v6 Therefore, we overwrite it
422 protocol = IPProtocols.ICMPV6.getValue();
424 ipv6ext_proto_msg.put(protocol);
425 return (ipv6ext_proto_msg.array());
428 private byte[] getIPv6ExtensionTOSMatchMsg(byte tos) {
429 ByteBuffer ipv6ext_tos_msg = ByteBuffer.allocate(5);
430 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
431 OF_Match_Types.MATCH_OF_IP_TOS.getValue(), 0, 1);
432 ipv6ext_tos_msg.putInt(nxm_header);
433 ipv6ext_tos_msg.put(tos);
434 return (ipv6ext_tos_msg.array());
437 private byte[] getIPv6ExtensionTCPSrcPortMatchMsg(short src_port) {
438 ByteBuffer ipv6ext_tcp_srcport_msg = ByteBuffer.allocate(6);
439 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
440 OF_Match_Types.MATCH_OF_TCP_SRC.getValue(), 0, 2);
441 ipv6ext_tcp_srcport_msg.putInt(nxm_header);
442 ipv6ext_tcp_srcport_msg.putShort(src_port);
443 return (ipv6ext_tcp_srcport_msg.array());
446 private byte[] getIPv6ExtensionTCPDstPortMatchMsg(short dst_port) {
447 ByteBuffer ipv6ext_tcp_dstport_msg = ByteBuffer.allocate(6);
448 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
449 OF_Match_Types.MATCH_OF_TCP_DST.getValue(), 0, 2);
450 ipv6ext_tcp_dstport_msg.putInt(nxm_header);
451 ipv6ext_tcp_dstport_msg.putShort(dst_port);
452 return (ipv6ext_tcp_dstport_msg.array());
455 private byte[] getIPv6ExtensionUDPSrcPortMatchMsg(short src_port) {
456 ByteBuffer ipv6ext_udp_srcport_msg = ByteBuffer.allocate(6);
457 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
458 OF_Match_Types.MATCH_OF_UDP_SRC.getValue(), 0, 2);
459 ipv6ext_udp_srcport_msg.putInt(nxm_header);
460 ipv6ext_udp_srcport_msg.putShort(src_port);
461 return (ipv6ext_udp_srcport_msg.array());
464 private byte[] getIPv6ExtensionUDPDstPortMatchMsg(short dst_port) {
465 ByteBuffer ipv6ext_udp_dstport_msg = ByteBuffer.allocate(6);
466 int nxm_header = getIPv6ExtensionMatchHeader(Extension_Types.OF_10,
467 OF_Match_Types.MATCH_OF_UDP_DST.getValue(), 0, 2);
468 ipv6ext_udp_dstport_msg.putInt(nxm_header);
469 ipv6ext_udp_dstport_msg.putShort(dst_port);
470 return (ipv6ext_udp_dstport_msg.array());
474 * Sets this (V6Match) object's member variables based on a comma-separated key=value pair similar to OFMatch's fromString.
476 * @param match a key=value comma separated string.
479 public void fromString(String match) throws IllegalArgumentException {
480 if (match.equals("") || match.equalsIgnoreCase("any")
481 || match.equalsIgnoreCase("all") || match.equals("[]"))
483 String[] tokens = match.split("[\\[,\\]]");
486 if (tokens[0].equals("OFMatch"))
488 this.wildcards = OFPFW_ALL;
490 for (i = initArg; i < tokens.length; i++) {
491 values = tokens[i].split("=");
492 if (values.length != 2)
493 throw new IllegalArgumentException("Token " + tokens[i]
494 + " does not have form 'key=value' parsing " + match);
495 values[0] = values[0].toLowerCase(); // try to make this case insens
496 if (values[0].equals(STR_IN_PORT) || values[0].equals("input_port")) {
497 this.inputPort = U16.t(Integer.valueOf(values[1]));
498 inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
500 } else if (values[0].equals(STR_DL_DST)
501 || values[0].equals("eth_dst")) {
502 this.dataLayerDestination = HexEncode
503 .bytesFromHexString(values[1]);
504 dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
506 } else if (values[0].equals(STR_DL_SRC)
507 || values[0].equals("eth_src")) {
508 this.dataLayerSource = HexEncode.bytesFromHexString(values[1]);
509 dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
511 this.wildcards &= ~OFPFW_DL_SRC;
512 } else if (values[0].equals(STR_DL_TYPE)
513 || values[0].equals("eth_type")) {
514 if (values[1].startsWith("0x"))
515 this.dataLayerType = U16.t(Integer.valueOf(values[1]
516 .replaceFirst("0x", ""), 16));
518 this.dataLayerType = U16.t(Integer.valueOf(values[1]));
519 ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
521 } else if (values[0].equals(STR_DL_VLAN)) {
522 this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1]));
523 dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
525 } else if (values[0].equals(STR_DL_VLAN_PCP)) {
526 this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short
527 .valueOf(values[1]));
528 this.wildcards &= ~OFPFW_DL_VLAN_PCP;
529 } else if (values[0].equals(STR_NW_DST)
530 || values[0].equals("ip_dst")) {
532 if (values[1].contains("/")) {
533 String ipv6addr_wmask[] = values[1].split("/");
534 this.nwDst = InetAddress.getByName(ipv6addr_wmask[0]);
535 this.dstIPv6SubnetMaskbits = Short
536 .valueOf(ipv6addr_wmask[1]);
537 nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
540 this.nwDst = InetAddress.getByName(values[1]);
541 nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
544 } catch (UnknownHostException e) {
547 } else if (values[0].equals(STR_NW_SRC)
548 || values[0].equals("ip_src")) {
550 if (values[1].contains("/")) {
551 String ipv6addr_wmask[] = values[1].split("/");
552 this.nwSrc = InetAddress.getByName(ipv6addr_wmask[0]);
553 this.srcIPv6SubnetMaskbits = Short
554 .valueOf(ipv6addr_wmask[1]);
555 nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
558 this.nwSrc = InetAddress.getByName(values[1]);
559 nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
562 } catch (UnknownHostException e) {
565 } else if (values[0].equals(STR_NW_PROTO)) {
566 this.networkProtocol = U8.t(Short.valueOf(values[1]));
567 if (!(this.networkProtocol == 0)) {
569 * if user selects proto 0, don't use it
571 nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
574 } else if (values[0].equals(STR_NW_TOS)) {
575 this.networkTypeOfService = U8.t(Short.valueOf(values[1]));
576 nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
578 } else if (values[0].equals(STR_TP_DST)) {
579 this.transportDestination = U16.t(Integer.valueOf(values[1]));
580 tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
582 } else if (values[0].equals(STR_TP_SRC)) {
583 this.transportSource = U16.t(Integer.valueOf(values[1]));
584 tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
587 throw new IllegalArgumentException("unknown token " + tokens[i]
588 + " parsing " + match);
592 * In a V6 extension message action list should be preceded by a padding of 0 to
593 * 7 bytes based upon following formula.
596 pad_size = (short) (((match_len + 7) / 8) * 8 - match_len);
601 * Write this message's binary format to the specified ByteBuffer
607 public void writeTo(ByteBuffer data) {
608 if (inputPortState == MatchFieldState.MATCH_FIELD_ONLY) {
609 byte[] ipv6ext_ingress_port_msg = getIPv6ExtensionPortMatchMsg(this.inputPort);
610 data.put(ipv6ext_ingress_port_msg);
612 if (ethTypeState == MatchFieldState.MATCH_FIELD_ONLY) {
613 byte[] ipv6ext_ether_type_msg = getIPv6ExtensionEtherTypeMatchMsg(this.dataLayerType);
614 data.put(ipv6ext_ether_type_msg);
616 if (dlDestState == MatchFieldState.MATCH_FIELD_ONLY) {
617 byte[] ipv6ext_destmac_msg = getIPv6ExtensionDestMacMatchMsg(this.dataLayerDestination);
618 data.put(ipv6ext_destmac_msg);
620 if (dlSourceState == MatchFieldState.MATCH_FIELD_ONLY) {
621 byte[] ipv6ext_srcmac_msg = getIPv6ExtensionSrcMacMatchMsg(this.dataLayerSource);
622 data.put(ipv6ext_srcmac_msg);
624 if (dlVlanState == MatchFieldState.MATCH_FIELD_ONLY) {
625 byte[] ipv6ext_vlan_id_msg = getIPv6ExtensionVlanIDMatchMsg(this.dataLayerVirtualLan);
626 data.put(ipv6ext_vlan_id_msg);
628 if (nwSrcState == MatchFieldState.MATCH_FIELD_ONLY) {
629 byte[] ipv6ext_src_ipv6_msg = getIPv6ExtensionSrcIPv6MatchMsg(this.nwSrc
631 data.put(ipv6ext_src_ipv6_msg);
632 } else if (nwSrcState == MatchFieldState.MATCH_FIELD_WITH_MASK) {
633 byte[] ipv6ext_src_ipv6_with_mask_msg = getIPv6ExtensionSrcIPv6MatchwithMaskMsg(
634 this.nwSrc.getAddress(), this.srcIPv6SubnetMaskbits);
635 data.put(ipv6ext_src_ipv6_with_mask_msg);
637 if (nwDstState == MatchFieldState.MATCH_FIELD_ONLY) {
638 byte[] ipv6ext_dst_ipv6_msg = getIPv6ExtensionDstIPv6MatchMsg(this.nwDst
640 data.put(ipv6ext_dst_ipv6_msg);
641 } else if (nwDstState == MatchFieldState.MATCH_FIELD_WITH_MASK) {
642 byte[] ipv6ext_dst_ipv6_with_mask_msg = getIPv6ExtensionDstIPv6MatchwithMaskMsg(
643 this.nwDst.getAddress(), this.dstIPv6SubnetMaskbits);
644 data.put(ipv6ext_dst_ipv6_with_mask_msg);
646 if (nwProtoState == MatchFieldState.MATCH_FIELD_ONLY) {
647 byte[] ipv6ext_protocol_msg = getIPv6ExtensionProtocolMatchMsg(this.networkProtocol);
648 if (ipv6ext_protocol_msg != null) {
649 data.put(ipv6ext_protocol_msg);
652 if (nwTosState == MatchFieldState.MATCH_FIELD_ONLY) {
653 byte[] ipv6ext_tos_msg = getIPv6ExtensionTOSMatchMsg(this.networkTypeOfService);
654 data.put(ipv6ext_tos_msg);
656 if (tpSrcState == MatchFieldState.MATCH_FIELD_ONLY) {
657 byte[] ipv6ext_srcport_msg = null;
658 if (this.networkProtocol == IPProtocols.TCP.getValue()) {
659 ipv6ext_srcport_msg = getIPv6ExtensionTCPSrcPortMatchMsg(this.transportSource);
660 } else if (this.networkProtocol == IPProtocols.UDP.getValue()) {
661 ipv6ext_srcport_msg = getIPv6ExtensionUDPSrcPortMatchMsg(this.transportSource);
663 if (ipv6ext_srcport_msg != null) {
664 data.put(ipv6ext_srcport_msg);
667 if (tpDstState == MatchFieldState.MATCH_FIELD_ONLY) {
668 byte[] ipv6ext_dstport_msg = null;
669 if (this.networkProtocol == IPProtocols.TCP.getValue()) {
670 ipv6ext_dstport_msg = getIPv6ExtensionTCPDstPortMatchMsg(this.transportDestination);
671 } else if (this.networkProtocol == IPProtocols.UDP.getValue()) {
672 ipv6ext_dstport_msg = getIPv6ExtensionUDPDstPortMatchMsg(this.transportDestination);
674 if (ipv6ext_dstport_msg != null) {
675 data.put(ipv6ext_dstport_msg);
678 logger.trace("{}", this.toString());
682 private void readInPort(ByteBuffer data, int nxmLen, boolean hasMask) {
683 if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
685 * mask is not allowed for inport port
688 super.setInputPort(data.getShort());
689 this.inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
690 this.wildcards ^= (1 << 0); // Sync with 0F 1.0 Match
694 private void readDataLinkDestination(ByteBuffer data, int nxmLen,
697 if ((nxmLen != 2 * 6) || (data.remaining() < 2 * 6))
700 byte[] bytes = new byte[6];
702 super.setDataLayerDestination(bytes);
703 this.dataLayerDestinationMask = new byte[6];
704 data.get(this.dataLayerDestinationMask);
705 this.dlDestState = MatchFieldState.MATCH_FIELD_WITH_MASK;
706 this.match_len += 16;
709 if ((nxmLen != 6) || (data.remaining() < 6))
712 byte[] bytes = new byte[6];
714 super.setDataLayerDestination(bytes);
715 this.dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
716 this.match_len += 10;
719 this.wildcards ^= (1 << 3); // Sync with 0F 1.0 Match
722 private void readDataLinkSource(ByteBuffer data, int nxmLen, boolean hasMask) {
724 * mask is not allowed in data link source
726 if ((nxmLen != 6) || (data.remaining() < 6) || (hasMask))
728 byte[] bytes = new byte[6];
730 super.setDataLayerSource(bytes);
731 this.dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
732 this.match_len += 10;
733 this.wildcards ^= (1 << 2); // Sync with 0F 1.0 Match
736 private void readEtherType(ByteBuffer data, int nxmLen, boolean hasMask) {
738 * mask is not allowed in ethertype
740 if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
742 super.setDataLayerType(data.getShort());
743 this.ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
744 this.wildcards ^= (1 << 4); // Sync with 0F 1.0 Match
748 private void readVlanTci(ByteBuffer data, int nxmLen, boolean hasMask) {
749 short vlan_mask = 0xfff;
751 if ((nxmLen != 2 * 2) || (data.remaining() < 2 * 2))
754 short vlan = data.getShort();
756 super.setDataLayerVirtualLan(vlan);
757 this.dataLayerVirtualLanMask = data.getShort();
758 this.dlVlanState = MatchFieldState.MATCH_FIELD_WITH_MASK;
760 this.wildcards ^= (1 << 20);
763 if ((nxmLen != 2) || (data.remaining() < 2))
766 short vlan = data.getShort();
768 super.setDataLayerVirtualLan(vlan);
769 this.dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
774 this.wildcards ^= (1 << 1); // Sync with 0F 1.0 Match
777 private void readIpTos(ByteBuffer data, int nxmLen, boolean hasMask) {
779 * mask is not allowed in IP TOS
781 if ((nxmLen != 1) || (data.remaining() < 1) || (hasMask))
783 super.setNetworkTypeOfService(data.get());
784 this.nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
786 this.wildcards ^= (1 << 21); // Sync with 0F 1.0 Match
789 private void readIpProto(ByteBuffer data, int nxmLen, boolean hasMask) {
791 * mask is not allowed in IP protocol
793 if ((nxmLen != 1) || (data.remaining() < 1) || (hasMask))
795 super.setNetworkProtocol(data.get());
796 this.nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
798 this.wildcards ^= (1 << 5); // Sync with 0F 1.0 Match
801 private void readIpv4Src(ByteBuffer data, int nxmLen, boolean hasMask) {
803 if ((nxmLen != 2 * 4) || (data.remaining() < 2 * 4))
806 byte[] sbytes = new byte[4];
809 this.nwSrc = InetAddress.getByAddress(sbytes);
810 } catch (UnknownHostException e) {
813 byte[] mbytes = new byte[4];
816 this.networkSourceMask = InetAddress.getByAddress(mbytes);
817 } catch (UnknownHostException e) {
820 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
821 this.match_len += 12;
822 int prefixlen = getNetworkMaskPrefixLength(mbytes);
823 this.wildcards ^= (((1 << 6) - 1) << 8); // Sync with 0F 1.0 Match
824 this.wildcards |= ((32 - prefixlen) << 8); // Sync with 0F 1.0 Match
828 if ((nxmLen != 4) || (data.remaining() < 4))
831 byte[] sbytes = new byte[4];
834 this.nwSrc = InetAddress.getByAddress(sbytes);
835 } catch (UnknownHostException e) {
838 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
840 this.wildcards ^= (((1 << 6) - 1) << 8); // Sync with 0F 1.0 Match
845 private void readIpv4Dst(ByteBuffer data, int nxmLen, boolean hasMask) {
847 if ((nxmLen != 2 * 4) || (data.remaining() < 2 * 4))
850 byte[] dbytes = new byte[4];
853 this.nwDst = InetAddress.getByAddress(dbytes);
854 } catch (UnknownHostException e) {
857 byte[] mbytes = new byte[4];
860 this.networkDestinationMask = InetAddress
861 .getByAddress(mbytes);
862 } catch (UnknownHostException e) {
865 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
866 this.match_len += 12;
867 int prefixlen = getNetworkMaskPrefixLength(mbytes);
868 this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0 Match
869 this.wildcards |= ((32 - prefixlen) << 14); // Sync with 0F 1.0 Match
872 if ((nxmLen != 4) || (data.remaining() < 4))
875 byte[] dbytes = new byte[4];
878 this.nwDst = InetAddress.getByAddress(dbytes);
879 } catch (UnknownHostException e) {
882 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
883 this.wildcards ^= (((1 << 6) - 1) << 14); // Sync with 0F 1.0 Match
889 private void readTcpSrc(ByteBuffer data, int nxmLen, boolean hasMask) {
891 * mask is not allowed in TCP SRC
893 if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
895 super.setTransportSource(data.getShort());
896 this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
898 this.wildcards ^= (1 << 6); // Sync with 0F 1.0 Match
901 private void readTcpDst(ByteBuffer data, int nxmLen, boolean hasMask) {
903 * mask is not allowed in TCP DST
905 if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
907 super.setTransportDestination(data.getShort());
908 this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
910 this.wildcards ^= (1 << 7); // Sync with 0F 1.0 Match
913 private void readUdpSrc(ByteBuffer data, int nxmLen, boolean hasMask) {
915 * mask is not allowed in UDP SRC
917 if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
919 super.setTransportSource(data.getShort());
920 this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
922 this.wildcards ^= (1 << 6); // Sync with 0F 1.0 Match
925 private void readUdpDst(ByteBuffer data, int nxmLen, boolean hasMask) {
927 * mask is not allowed in UDP DST
929 if ((nxmLen != 2) || (data.remaining() < 2) || (hasMask))
931 super.setTransportDestination(data.getShort());
932 this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
934 this.wildcards ^= (1 << 7); // Sync with 0F 1.0 Match
937 private void readIpv6Src(ByteBuffer data, int nxmLen, boolean hasMask) {
939 if ((nxmLen != 2 * 16) || (data.remaining() < 2 * 16))
942 byte[] sbytes = new byte[16];
945 this.nwSrc = InetAddress.getByAddress(sbytes);
946 } catch (UnknownHostException e) {
949 byte[] mbytes = new byte[16];
952 this.networkSourceMask = InetAddress.getByAddress(mbytes);
953 } catch (UnknownHostException e) {
956 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
957 this.match_len += 36;
960 if ((nxmLen != 16) || (data.remaining() < 16))
963 byte[] sbytes = new byte[16];
966 this.nwSrc = InetAddress.getByAddress(sbytes);
967 } catch (UnknownHostException e) {
970 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
971 this.match_len += 20;
976 private void readIpv6Dst(ByteBuffer data, int nxmLen, boolean hasMask) {
978 if ((nxmLen != 2 * 16) || (data.remaining() < 2 * 16))
981 byte[] dbytes = new byte[16];
984 this.nwDst = InetAddress.getByAddress(dbytes);
985 } catch (UnknownHostException e) {
988 byte[] mbytes = new byte[16];
991 this.networkDestinationMask = InetAddress
992 .getByAddress(mbytes);
993 } catch (UnknownHostException e) {
996 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
997 this.match_len += 36;
1000 if ((nxmLen != 16) || (data.remaining() < 16))
1003 byte[] dbytes = new byte[16];
1006 this.nwDst = InetAddress.getByAddress(dbytes);
1007 } catch (UnknownHostException e) {
1010 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
1011 this.match_len += 20;
1017 public String toString() {
1018 return "V6Match[" + ReflectionToStringBuilder.toString(this) + "]";
1022 * Read the data corresponding to the match field (received from the wire)
1023 * Input: data: match field(s). Since match field is of variable length, the whole data that are passed in
1024 * are assumed to fem0tbd.be the match fields.
1029 public void readFrom(ByteBuffer data) {
1030 readFromInternal(data);
1031 postprocessWildCardInfo();
1035 private void readFromInternal(ByteBuffer data) {
1037 while (data.remaining() > 0) {
1038 if (data.remaining() < 4) {
1040 * at least 4 bytes for each match header
1042 logger.error("Invalid Vendor Extension Header. Size {}", data
1047 * read the 4 byte match header
1049 int nxmVendor = data.getShort();
1051 int nxmField = b >> 1;
1052 boolean hasMask = ((b & 0x01) == 1) ? true : false;
1053 int nxmLen = data.get();
1054 if (nxmVendor == Extension_Types.OF_10.getValue()) {
1055 if (nxmField == OF_Match_Types.MATCH_OF_IN_PORT.getValue()) {
1056 readInPort(data, nxmLen, hasMask);
1057 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_DST
1059 readDataLinkDestination(data, nxmLen, hasMask);
1060 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_SRC
1062 readDataLinkSource(data, nxmLen, hasMask);
1063 } else if (nxmField == OF_Match_Types.MATCH_OF_ETH_TYPE
1065 readEtherType(data, nxmLen, hasMask);
1066 } else if (nxmField == OF_Match_Types.MATCH_OF_VLAN_TCI
1068 readVlanTci(data, nxmLen, hasMask);
1069 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_TOS
1071 readIpTos(data, nxmLen, hasMask);
1072 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_PROTO
1074 readIpProto(data, nxmLen, hasMask);
1075 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_SRC
1077 readIpv4Src(data, nxmLen, hasMask);
1078 } else if (nxmField == OF_Match_Types.MATCH_OF_IP_DST
1080 readIpv4Dst(data, nxmLen, hasMask);
1081 } else if (nxmField == OF_Match_Types.MATCH_OF_TCP_SRC
1083 readTcpSrc(data, nxmLen, hasMask);
1084 } else if (nxmField == OF_Match_Types.MATCH_OF_TCP_DST
1086 readTcpDst(data, nxmLen, hasMask);
1087 } else if (nxmField == OF_Match_Types.MATCH_OF_UDP_SRC
1089 readUdpSrc(data, nxmLen, hasMask);
1090 } else if (nxmField == OF_Match_Types.MATCH_OF_UDP_DST
1092 readUdpDst(data, nxmLen, hasMask);
1094 // unexpected nxmField
1097 } else if (nxmVendor == Extension_Types.IPV6EXT.getValue()) {
1098 if (nxmField == IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_SRC
1100 readIpv6Src(data, nxmLen, hasMask);
1101 } else if (nxmField == IPv6Extension_Match_Types.MATCH_IPV6EXT_IPV6_DST
1103 readIpv6Dst(data, nxmLen, hasMask);
1105 // unexpected nxmField
1109 // invalid nxmVendor
1115 private void postprocessWildCardInfo() {
1116 // Sync with 0F 1.0 Match
1117 if (super.getDataLayerType() == 0x800) {
1118 if (((this.wildcards >> 8) & 0x3f) == 0x3f) {
1119 //ipv4 src processing
1120 this.wildcards ^= (((1 << 5) - 1) << 8);
1122 if (((this.wildcards >> 14) & 0x3f) == 0x3f) {
1123 //ipv4 dest processing
1124 this.wildcards ^= (((1 << 5) - 1) << 14);
1132 public V6Match clone() {
1134 V6Match ret = (V6Match) super.clone();
1136 if (this.nwSrc != null) {
1137 ret.nwSrc = InetAddress.getByAddress(this.nwSrc.getAddress());
1139 if (this.nwDst != null) {
1140 ret.nwDst = InetAddress.getByAddress(this.nwDst.getAddress());
1143 } catch (UnknownHostException e) {
1144 throw new RuntimeException(e);
1154 public InetAddress getNetworkDest() {
1164 public void setNetworkSrc(InetAddress address) {
1174 public void setNetworkDest(InetAddress address) {
1184 public InetAddress getNetworkSrc() {
1188 private int getNetworkMaskPrefixLength(byte[] netMask) {
1189 ByteBuffer nm = ByteBuffer.wrap(netMask);
1190 int trailingZeros = Integer.numberOfTrailingZeros(nm.getInt());
1191 return 32 - trailingZeros;
1194 public short getInputPortMask() {
1195 return inputPortMask;
1198 public void setInputPort(short port, short mask) {
1199 super.inputPort = port;
1200 this.inputPortState = MatchFieldState.MATCH_FIELD_ONLY;
1202 // Looks like mask is not allowed for input port. Will discard it
1205 public byte[] getDataLayerSourceMask() {
1206 return dataLayerSourceMask;
1209 public void setDataLayerSource(byte[] mac, byte[] mask) {
1211 System.arraycopy(mac, 0, super.dataLayerSource, 0, mac.length);
1214 this.dlSourceState = MatchFieldState.MATCH_FIELD_ONLY;
1215 this.match_len += 10;
1217 if (this.dataLayerSourceMask == null) {
1218 this.dataLayerSourceMask = new byte[mask.length];
1220 System.arraycopy(mask, 0, this.dataLayerSourceMask, 0, mask.length);
1221 this.dlSourceState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1222 this.match_len += 16;
1226 public byte[] getDataLayerDestinationMask() {
1227 return dataLayerDestinationMask;
1230 public void setDataLayerDestination(byte[] mac, byte[] mask) {
1232 System.arraycopy(mac, 0, super.dataLayerDestination, 0, mac.length);
1235 this.dlDestState = MatchFieldState.MATCH_FIELD_ONLY;
1236 this.match_len += 10;
1238 if (this.dataLayerDestinationMask == null) {
1239 this.dataLayerDestinationMask = new byte[mask.length];
1241 System.arraycopy(mask, 0, this.dataLayerDestinationMask, 0,
1243 this.dlDestState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1244 this.match_len += 16;
1248 public short getDataLayerVirtualLanMask() {
1249 return dataLayerVirtualLanMask;
1252 public void setDataLayerVirtualLan(short vlan, short mask) {
1253 super.dataLayerVirtualLan = vlan;
1255 this.dlVlanState = MatchFieldState.MATCH_FIELD_ONLY;
1256 this.match_len += 6;
1258 this.dataLayerVirtualLanMask = mask;
1259 this.dlVlanState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1260 this.match_len += 8;
1264 public void setDataLayerVirtualLanPriorityCodePoint(byte pcp, byte mask) {
1265 super.dataLayerVirtualLanPriorityCodePoint = pcp;
1268 public void setDataLayerType(short ethType, short mask) {
1270 super.dataLayerType = ethType;
1271 this.ethTypeState = MatchFieldState.MATCH_FIELD_ONLY;
1272 this.match_len += 6;
1275 public void setNetworkTypeOfService(byte tos, byte mask) {
1277 super.networkTypeOfService = tos;
1278 this.nwTosState = MatchFieldState.MATCH_FIELD_ONLY;
1282 public void setNetworkProtocol(byte ipProto, byte mask) {
1284 super.networkProtocol = ipProto;
1285 this.nwProtoState = MatchFieldState.MATCH_FIELD_ONLY;
1286 this.match_len += 5;
1289 public InetAddress getNetworkSourceMask() {
1290 return networkSourceMask;
1293 public void setNetworkSource(InetAddress address, InetAddress mask) {
1294 this.nwSrc = address;
1296 this.nwSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1297 this.match_len += (address instanceof Inet6Address) ? 20 : 8;
1299 this.networkSourceMask = mask;
1300 this.nwSrcState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1301 this.match_len += (address instanceof Inet6Address) ? 36 : 12;
1305 public InetAddress getNetworkDestinationMask() {
1306 return networkDestinationMask;
1309 public void setNetworkDestination(InetAddress address, InetAddress mask) {
1310 this.nwDst = address;
1312 this.nwDstState = MatchFieldState.MATCH_FIELD_ONLY;
1313 this.match_len += (address instanceof Inet6Address) ? 20 : 8;
1315 this.networkDestinationMask = mask;
1316 this.nwDstState = MatchFieldState.MATCH_FIELD_WITH_MASK;
1317 this.match_len += (address instanceof Inet6Address) ? 36 : 12;
1321 public void setTransportSource(short tpSrc, short mask) {
1323 super.transportSource = tpSrc;
1324 this.tpSrcState = MatchFieldState.MATCH_FIELD_ONLY;
1325 this.match_len += 6;
1328 public short getTransportDestinationMask() {
1329 return transportDestinationMask;
1332 public void setTransportDestination(short tpDst, short mask) {
1334 super.transportDestination = tpDst;
1335 this.tpDstState = MatchFieldState.MATCH_FIELD_ONLY;
1336 this.match_len += 6;
1339 private byte[] getIPv6NetworkMaskinBytes(short num) {
1340 byte[] nbytes = new byte[16];
1345 for (i = 0; i < quot; i++) {
1346 nbytes[i] = (byte) 0xff;
1350 nbytes[i] = (byte) 0xff;
1351 nbytes[i] <<= 8 - bits;