1 package org.openflow.protocol;
3 import java.io.Serializable;
4 import java.nio.ByteBuffer;
5 import java.util.Arrays;
7 import org.openflow.util.HexString;
8 import org.openflow.util.U16;
9 import org.openflow.util.U8;
12 * Represents an ofp_match structure
14 * @author David Erickson (daviderickson@cs.stanford.edu)
15 * @author Rob Sherwood (rob.sherwood@stanford.edu)
18 public class OFMatch implements Cloneable, Serializable {
22 private static final long serialVersionUID = 1L;
23 public static int MINIMUM_LENGTH = 40;
24 final public static int OFPFW_ALL = ((1 << 22) - 1);
26 final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */
27 final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */
28 final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */
29 final public static int OFPFW_DL_DST = 1 << 3; /*
30 * Ethernet destination
33 final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */
34 final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */
35 final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */
36 final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */
39 * IP source address wildcard bit count. 0 is exact match, 1 ignores the
40 * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
41 * the entire field. This is the *opposite* of the usual convention where
42 * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded.
44 final public static int OFPFW_NW_SRC_SHIFT = 8;
45 final public static int OFPFW_NW_SRC_BITS = 6;
46 final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT;
47 final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT;
49 /* IP destination address wildcard bit count. Same format as source. */
50 final public static int OFPFW_NW_DST_SHIFT = 14;
51 final public static int OFPFW_NW_DST_BITS = 6;
52 final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT;
53 final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT;
55 final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */
56 final public static int OFPFW_NW_TOS = 1 << 21; /*
57 * IP ToS (DSCP field, 6
61 /* List of Strings for marshalling and unmarshalling to human readable forms */
62 final public static String STR_IN_PORT = "in_port";
63 final public static String STR_DL_DST = "dl_dst";
64 final public static String STR_DL_SRC = "dl_src";
65 final public static String STR_DL_TYPE = "dl_type";
66 final public static String STR_DL_VLAN = "dl_vlan";
67 final public static String STR_DL_VLAN_PCP = "dl_vpcp";
68 final public static String STR_NW_DST = "nw_dst";
69 final public static String STR_NW_SRC = "nw_src";
70 final public static String STR_NW_PROTO = "nw_proto";
71 final public static String STR_NW_TOS = "nw_tos";
72 final public static String STR_TP_DST = "tp_dst";
73 final public static String STR_TP_SRC = "tp_src";
75 protected int wildcards;
76 protected short inputPort;
77 protected byte[] dataLayerSource;
78 protected byte[] dataLayerDestination;
79 protected short dataLayerVirtualLan;
80 protected byte dataLayerVirtualLanPriorityCodePoint;
81 protected short dataLayerType;
82 protected byte networkTypeOfService;
83 protected byte networkProtocol;
84 protected int networkSource;
85 protected int networkDestination;
86 protected short transportSource;
87 protected short transportDestination;
90 * By default, create a OFMatch that matches everything
92 * (mostly because it's the least amount of work to make a valid OFMatch)
95 this.wildcards = OFPFW_ALL;
96 this.dataLayerDestination = new byte[6];
97 this.dataLayerSource = new byte[6];
103 * @return an arrays of bytes
105 public byte[] getDataLayerDestination() {
106 return this.dataLayerDestination;
112 * @param dataLayerDestination
114 public OFMatch setDataLayerDestination(byte[] dataLayerDestination) {
115 this.dataLayerDestination = dataLayerDestination;
120 * Set dl_dst, but first translate to byte[] using HexString
123 * A colon separated string of 6 pairs of octets, e..g.,
124 * "00:17:42:EF:CD:8D"
126 public OFMatch setDataLayerDestination(String mac) {
127 byte bytes[] = HexString.fromHexString(mac);
128 if (bytes.length != 6)
129 throw new IllegalArgumentException(
130 "expected string with 6 octets, got '" + mac + "'");
131 this.dataLayerDestination = bytes;
138 * @return an array of bytes
140 public byte[] getDataLayerSource() {
141 return this.dataLayerSource;
147 * @param dataLayerSource
149 public OFMatch setDataLayerSource(byte[] dataLayerSource) {
150 this.dataLayerSource = dataLayerSource;
155 * Set dl_src, but first translate to byte[] using HexString
158 * A colon separated string of 6 pairs of octets, e..g.,
159 * "00:17:42:EF:CD:8D"
161 public OFMatch setDataLayerSource(String mac) {
162 byte bytes[] = HexString.fromHexString(mac);
163 if (bytes.length != 6)
164 throw new IllegalArgumentException(
165 "expected string with 6 octets, got '" + mac + "'");
166 this.dataLayerSource = bytes;
175 public short getDataLayerType() {
176 return this.dataLayerType;
182 * @param dataLayerType
184 public OFMatch setDataLayerType(short dataLayerType) {
185 this.dataLayerType = dataLayerType;
192 * @return vlan tag; VLAN_NONE == no tag
194 public short getDataLayerVirtualLan() {
195 return this.dataLayerVirtualLan;
201 * @param dataLayerVirtualLan
203 public OFMatch setDataLayerVirtualLan(short dataLayerVirtualLan) {
204 this.dataLayerVirtualLan = dataLayerVirtualLan;
213 public byte getDataLayerVirtualLanPriorityCodePoint() {
214 return this.dataLayerVirtualLanPriorityCodePoint;
222 public OFMatch setDataLayerVirtualLanPriorityCodePoint(byte pcp) {
223 this.dataLayerVirtualLanPriorityCodePoint = pcp;
232 public short getInputPort() {
233 return this.inputPort;
241 public OFMatch setInputPort(short inputPort) {
242 this.inputPort = inputPort;
251 public int getNetworkDestination() {
252 return this.networkDestination;
258 * @param networkDestination
260 public OFMatch setNetworkDestination(int networkDestination) {
261 this.networkDestination = networkDestination;
266 * Parse this match's wildcard fields and return the number of significant
267 * bits in the IP destination field.
269 * NOTE: this returns the number of bits that are fixed, i.e., like CIDR,
270 * not the number of bits that are free like OpenFlow encodes.
272 * @return a number between 0 (matches all IPs) and 63 ( 32>= implies exact
275 public int getNetworkDestinationMaskLen() {
277 .max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
282 * Parse this match's wildcard fields and return the number of significant
283 * bits in the IP destination field.
285 * NOTE: this returns the number of bits that are fixed, i.e., like CIDR,
286 * not the number of bits that are free like OpenFlow encodes.
288 * @return a number between 0 (matches all IPs) and 32 (exact match)
290 public int getNetworkSourceMaskLen() {
292 .max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
301 public byte getNetworkProtocol() {
302 return this.networkProtocol;
308 * @param networkProtocol
310 public OFMatch setNetworkProtocol(byte networkProtocol) {
311 this.networkProtocol = networkProtocol;
320 public int getNetworkSource() {
321 return this.networkSource;
327 * @param networkSource
329 public OFMatch setNetworkSource(int networkSource) {
330 this.networkSource = networkSource;
339 public byte getNetworkTypeOfService() {
340 return this.networkTypeOfService;
346 * @param networkTypeOfService
348 public OFMatch setNetworkTypeOfService(byte networkTypeOfService) {
349 this.networkTypeOfService = networkTypeOfService;
358 public short getTransportDestination() {
359 return this.transportDestination;
365 * @param transportDestination
367 public OFMatch setTransportDestination(short transportDestination) {
368 this.transportDestination = transportDestination;
377 public short getTransportSource() {
378 return this.transportSource;
384 * @param transportSource
386 public OFMatch setTransportSource(short transportSource) {
387 this.transportSource = transportSource;
396 public int getWildcards() {
397 return this.wildcards;
405 public OFMatch setWildcards(int wildcards) {
406 this.wildcards = wildcards;
411 * Initializes this OFMatch structure with the corresponding data from the
414 * Must specify the input port, to ensure that this.in_port is set
417 * Specify OFPort.NONE or OFPort.ANY if input port not applicable or
423 * the port the packet arrived on
425 public OFMatch loadFromPacket(byte[] packetData, short inputPort) {
427 int transportOffset = 34;
428 ByteBuffer packetDataBB = ByteBuffer.wrap(packetData);
429 int limit = packetDataBB.limit();
431 this.wildcards = 0; // all fields have explicit entries
433 this.inputPort = inputPort;
435 if (inputPort == OFPort.OFPP_ALL.getValue())
436 this.wildcards |= OFPFW_IN_PORT;
438 assert (limit >= 14);
440 this.dataLayerDestination = new byte[6];
441 packetDataBB.get(this.dataLayerDestination);
443 this.dataLayerSource = new byte[6];
444 packetDataBB.get(this.dataLayerSource);
446 this.dataLayerType = packetDataBB.getShort();
448 if (getDataLayerType() != (short) 0x8100) { // need cast to avoid signed
450 setDataLayerVirtualLan((short) 0xffff);
451 setDataLayerVirtualLanPriorityCodePoint((byte) 0);
454 scratch = packetDataBB.getShort();
455 setDataLayerVirtualLan((short) (0xfff & scratch));
456 setDataLayerVirtualLanPriorityCodePoint((byte) ((0xe000 & scratch) >> 13));
457 this.dataLayerType = packetDataBB.getShort();
460 switch (getDataLayerType()) {
463 // check packet length
464 scratch = packetDataBB.get();
465 scratch = (short) (0xf & scratch);
466 transportOffset = (packetDataBB.position() - 1) + (scratch * 4);
468 scratch = packetDataBB.get();
469 setNetworkTypeOfService((byte) ((0xfc & scratch) >> 2));
471 packetDataBB.position(packetDataBB.position() + 7);
472 this.networkProtocol = packetDataBB.get();
474 packetDataBB.position(packetDataBB.position() + 2);
475 this.networkSource = packetDataBB.getInt();
477 this.networkDestination = packetDataBB.getInt();
478 packetDataBB.position(transportOffset);
482 int arpPos = packetDataBB.position();
484 scratch = packetDataBB.getShort(arpPos + 6);
485 setNetworkProtocol((byte) (0xff & scratch));
487 scratch = packetDataBB.getShort(arpPos + 2);
488 // if ipv4 and addr len is 4
489 if (scratch == 0x800 && packetDataBB.get(arpPos + 5) == 4) {
491 this.networkSource = packetDataBB.getInt(arpPos + 14);
493 this.networkDestination = packetDataBB.getInt(arpPos + 24);
496 setNetworkDestination(0);
500 setNetworkTypeOfService((byte) 0);
501 setNetworkProtocol((byte) 0);
503 setNetworkDestination(0);
507 switch (getNetworkProtocol()) {
511 this.transportSource = U8.f(packetDataBB.get());
513 this.transportDestination = U8.f(packetDataBB.get());
518 this.transportSource = packetDataBB.getShort();
520 this.transportDestination = packetDataBB.getShort();
525 this.transportSource = packetDataBB.getShort();
527 this.transportDestination = packetDataBB.getShort();
530 setTransportDestination((short) 0);
531 setTransportSource((short) 0);
538 * Read this message off the wire from the specified ByteBuffer
542 public void readFrom(ByteBuffer data) {
543 this.wildcards = data.getInt();
544 this.inputPort = data.getShort();
545 this.dataLayerSource = new byte[6];
546 data.get(this.dataLayerSource);
547 this.dataLayerDestination = new byte[6];
548 data.get(this.dataLayerDestination);
549 this.dataLayerVirtualLan = data.getShort();
550 this.dataLayerVirtualLanPriorityCodePoint = data.get();
552 this.dataLayerType = data.getShort();
553 this.networkTypeOfService = data.get();
554 this.networkProtocol = data.get();
557 this.networkSource = data.getInt();
558 this.networkDestination = data.getInt();
559 this.transportSource = data.getShort();
560 this.transportDestination = data.getShort();
564 * Write this message's binary format to the specified ByteBuffer
568 public void writeTo(ByteBuffer data) {
569 data.putInt(wildcards);
570 data.putShort(inputPort);
571 data.put(this.dataLayerSource);
572 data.put(this.dataLayerDestination);
573 data.putShort(dataLayerVirtualLan);
574 data.put(dataLayerVirtualLanPriorityCodePoint);
575 data.put((byte) 0x0); // pad
576 data.putShort(dataLayerType);
577 data.put(networkTypeOfService);
578 data.put(networkProtocol);
579 data.put((byte) 0x0); // pad
580 data.put((byte) 0x0); // pad
581 data.putInt(networkSource);
582 data.putInt(networkDestination);
583 data.putShort(transportSource);
584 data.putShort(transportDestination);
588 public int hashCode() {
589 final int prime = 131;
591 result = prime * result + Arrays.hashCode(dataLayerDestination);
592 result = prime * result + Arrays.hashCode(dataLayerSource);
593 result = prime * result + dataLayerType;
594 result = prime * result + dataLayerVirtualLan;
595 result = prime * result + dataLayerVirtualLanPriorityCodePoint;
596 result = prime * result + inputPort;
597 result = prime * result + networkDestination;
598 result = prime * result + networkProtocol;
599 result = prime * result + networkSource;
600 result = prime * result + networkTypeOfService;
601 result = prime * result + transportDestination;
602 result = prime * result + transportSource;
603 result = prime * result + wildcards;
608 public boolean equals(Object obj) {
615 if (!(obj instanceof OFMatch)) {
618 OFMatch other = (OFMatch) obj;
619 if (!Arrays.equals(dataLayerDestination, other.dataLayerDestination)) {
622 if (!Arrays.equals(dataLayerSource, other.dataLayerSource)) {
625 if (dataLayerType != other.dataLayerType) {
628 if (dataLayerVirtualLan != other.dataLayerVirtualLan) {
631 if (dataLayerVirtualLanPriorityCodePoint != other.dataLayerVirtualLanPriorityCodePoint) {
634 if (inputPort != other.inputPort) {
637 if (networkDestination != other.networkDestination) {
640 if (networkProtocol != other.networkProtocol) {
643 if (networkSource != other.networkSource) {
646 if (networkTypeOfService != other.networkTypeOfService) {
649 if (transportDestination != other.transportDestination) {
652 if (transportSource != other.transportSource) {
655 if ((wildcards & OFMatch.OFPFW_ALL) != (other.wildcards & OFPFW_ALL)) { // only
667 * Implement clonable interface
670 public OFMatch clone() {
672 OFMatch ret = (OFMatch) super.clone();
673 ret.dataLayerDestination = this.dataLayerDestination.clone();
674 ret.dataLayerSource = this.dataLayerSource.clone();
676 } catch (CloneNotSupportedException e) {
677 throw new RuntimeException(e);
682 * Output a dpctl-styled string, i.e., only list the elements that are not
685 * A match-everything OFMatch outputs "OFMatch[]"
688 * "OFMatch[dl_src:00:20:01:11:22:33,nw_src:192.168.0.0/24,tp_dst:80]"
691 public String toString() {
695 if ((wildcards & OFPFW_IN_PORT) == 0)
696 str += "," + STR_IN_PORT + "=" + U16.f(this.inputPort);
699 if ((wildcards & OFPFW_DL_DST) == 0)
700 str += "," + STR_DL_DST + "="
701 + HexString.toHexString(this.dataLayerDestination);
702 if ((wildcards & OFPFW_DL_SRC) == 0)
703 str += "," + STR_DL_SRC + "="
704 + HexString.toHexString(this.dataLayerSource);
705 if ((wildcards & OFPFW_DL_TYPE) == 0)
706 str += "," + STR_DL_TYPE + "=0x"
707 + Integer.toHexString(U16.f(this.dataLayerType));
708 if ((wildcards & OFPFW_DL_VLAN) == 0)
709 str += "," + STR_DL_VLAN + "=0x"
710 + Integer.toHexString(U16.f(this.dataLayerVirtualLan));
711 if ((wildcards & OFPFW_DL_VLAN_PCP) == 0)
715 + Integer.toHexString(U8
716 .f(this.dataLayerVirtualLanPriorityCodePoint));
719 if (getNetworkDestinationMaskLen() > 0)
723 + cidrToString(networkDestination,
724 getNetworkDestinationMaskLen());
725 if (getNetworkSourceMaskLen() > 0)
726 str += "," + STR_NW_SRC + "="
727 + cidrToString(networkSource, getNetworkSourceMaskLen());
728 if ((wildcards & OFPFW_NW_PROTO) == 0)
729 str += "," + STR_NW_PROTO + "=" + this.networkProtocol;
730 if ((wildcards & OFPFW_NW_TOS) == 0)
731 str += "," + STR_NW_TOS + "=" + this.networkTypeOfService;
734 if ((wildcards & OFPFW_TP_DST) == 0)
735 str += "," + STR_TP_DST + "=" + this.transportDestination;
736 if ((wildcards & OFPFW_TP_SRC) == 0)
737 str += "," + STR_TP_SRC + "=" + this.transportSource;
738 if ((str.length() > 0) && (str.charAt(0) == ','))
739 str = str.substring(1); // trim the leading ","
741 return "OFMatch[" + str + "]";
744 private String cidrToString(int ip, int prefix) {
747 str = ipToString(ip);
749 // use the negation of mask to fake endian magic
750 int mask = ~((1 << (32 - prefix)) - 1);
751 str = ipToString(ip & mask) + "/" + prefix;
758 * Set this OFMatch's parameters based on a comma-separated key=value pair
759 * dpctl-style string, e.g., from the output of OFMatch.toString() <br>
761 * Supported keys/values include <br>
769 * <TD>"in_port","input_port"
773 * <TD>"dl_src","eth_src", "dl_dst","eth_dst"
777 * <TD>"dl_type", "dl_vlan", "dl_vlan_pcp"
781 * <TD>"nw_src", "nw_dst", "ip_src", "ip_dst"
782 * <TD>CIDR-style netmask
785 * <TD>"tp_src","tp_dst"
786 * <TD>integer (max 64k)
790 * The CIDR-style netmasks assume 32 netmask if none given, so:
791 * "128.8.128.118/32" is the same as "128.8.128.118"
794 * a key=value comma separated string, e.g.
795 * "in_port=5,ip_dst=192.168.0.0/16,tp_src=80"
796 * @throws IllegalArgumentException
797 * on unexpected key or value
800 public void fromString(String match) throws IllegalArgumentException {
801 if (match.equals("") || match.equalsIgnoreCase("any")
802 || match.equalsIgnoreCase("all") || match.equals("[]"))
804 String[] tokens = match.split("[\\[,\\]]");
807 if (tokens[0].equals("OFMatch"))
809 this.wildcards = OFPFW_ALL;
811 for (i = initArg; i < tokens.length; i++) {
812 values = tokens[i].split("=");
813 if (values.length != 2)
814 throw new IllegalArgumentException("Token " + tokens[i]
815 + " does not have form 'key=value' parsing " + match);
816 values[0] = values[0].toLowerCase(); // try to make this case insens
817 if (values[0].equals(STR_IN_PORT) || values[0].equals("input_port")) {
818 this.inputPort = U16.t(Integer.valueOf(values[1]));
819 this.wildcards &= ~OFPFW_IN_PORT;
820 } else if (values[0].equals(STR_DL_DST)
821 || values[0].equals("eth_dst")) {
822 this.dataLayerDestination = HexString.fromHexString(values[1]);
823 this.wildcards &= ~OFPFW_DL_DST;
824 } else if (values[0].equals(STR_DL_SRC)
825 || values[0].equals("eth_src")) {
826 this.dataLayerSource = HexString.fromHexString(values[1]);
827 this.wildcards &= ~OFPFW_DL_SRC;
828 } else if (values[0].equals(STR_DL_TYPE)
829 || values[0].equals("eth_type")) {
830 if (values[1].startsWith("0x"))
831 this.dataLayerType = U16.t(Integer.valueOf(
832 values[1].replaceFirst("0x", ""), 16));
834 this.dataLayerType = U16.t(Integer.valueOf(values[1]));
835 this.wildcards &= ~OFPFW_DL_TYPE;
836 } else if (values[0].equals(STR_DL_VLAN)) {
837 this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1]));
838 this.wildcards &= ~OFPFW_DL_VLAN;
839 } else if (values[0].equals(STR_DL_VLAN_PCP)) {
840 this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short
841 .valueOf(values[1]));
842 this.wildcards &= ~OFPFW_DL_VLAN_PCP;
843 } else if (values[0].equals(STR_NW_DST)
844 || values[0].equals("ip_dst"))
845 setFromCIDR(values[1], STR_NW_DST);
846 else if (values[0].equals(STR_NW_SRC) || values[0].equals("ip_src"))
847 setFromCIDR(values[1], STR_NW_SRC);
848 else if (values[0].equals(STR_NW_PROTO)) {
849 this.networkProtocol = U8.t(Short.valueOf(values[1]));
850 this.wildcards &= ~OFPFW_NW_PROTO;
851 } else if (values[0].equals(STR_NW_TOS)) {
852 this.networkTypeOfService = U8.t(Short.valueOf(values[1]));
853 this.wildcards &= ~OFPFW_NW_TOS;
854 } else if (values[0].equals(STR_TP_DST)) {
855 this.transportDestination = U16.t(Integer.valueOf(values[1]));
856 this.wildcards &= ~OFPFW_TP_DST;
857 } else if (values[0].equals(STR_TP_SRC)) {
858 this.transportSource = U16.t(Integer.valueOf(values[1]));
859 this.wildcards &= ~OFPFW_TP_SRC;
861 throw new IllegalArgumentException("unknown token " + tokens[i]
862 + " parsing " + match);
867 * Set the networkSource or networkDestionation address and their wildcards
868 * from the CIDR string
871 * "192.168.0.0/16" or "172.16.1.5"
873 * one of STR_NW_DST or STR_NW_SRC
874 * @throws IllegalArgumentException
876 private void setFromCIDR(String cidr, String which)
877 throws IllegalArgumentException {
878 String values[] = cidr.split("/");
879 String[] ip_str = values[0].split("\\.");
881 ip += Integer.valueOf(ip_str[0]) << 24;
882 ip += Integer.valueOf(ip_str[1]) << 16;
883 ip += Integer.valueOf(ip_str[2]) << 8;
884 ip += Integer.valueOf(ip_str[3]);
885 int prefix = 32; // all bits are fixed, by default
887 if (values.length >= 2)
888 prefix = Integer.valueOf(values[1]);
889 int mask = 32 - prefix;
890 if (which.equals(STR_NW_DST)) {
891 this.networkDestination = ip;
892 this.wildcards = (wildcards & ~OFPFW_NW_DST_MASK)
893 | (mask << OFPFW_NW_DST_SHIFT);
894 } else if (which.equals(STR_NW_SRC)) {
895 this.networkSource = ip;
896 this.wildcards = (wildcards & ~OFPFW_NW_SRC_MASK)
897 | (mask << OFPFW_NW_SRC_SHIFT);
901 protected static String ipToString(int ip) {
902 return Integer.toString(U8.f((byte) ((ip & 0xff000000) >> 24))) + "."
903 + Integer.toString((ip & 0x00ff0000) >> 16) + "."
904 + Integer.toString((ip & 0x0000ff00) >> 8) + "."
905 + Integer.toString(ip & 0x000000ff);
909 * Reverses a match such that source and destination values plus
910 * corresponding masks are swapped. An input port must be explicitly
911 * passed in as the match does not contain an output port.
913 * @param inputPort new input port to use in match
914 * @param wildcardInputPort should the input port be wildcarded
916 * @return Reversed copy of match
918 public OFMatch reverse(short inputPort, boolean wildcardInputPort) {
919 OFMatch ret = this.clone();
921 // Set the input port
922 if (wildcardInputPort) {
924 ret.wildcards |= OFPFW_IN_PORT;
926 ret.inputPort = inputPort;
927 ret.wildcards &= ~OFPFW_IN_PORT;
930 // Switch the source/dest fields
931 ret.dataLayerDestination = this.dataLayerSource.clone();
932 ret.dataLayerSource = this.dataLayerDestination.clone();
934 ret.networkDestination = this.networkSource;
935 ret.networkSource = this.networkDestination;
937 ret.transportDestination = this.transportSource;
938 ret.transportSource = this.transportDestination;
940 // Switch the wildcards on source/dest fields
941 ret.wildcards &= ~(OFPFW_DL_DST | OFPFW_DL_SRC |
942 OFPFW_NW_DST_MASK | OFPFW_NW_SRC_MASK |
943 OFPFW_TP_DST | OFPFW_TP_SRC);
944 ret.wildcards |= ((this.wildcards & OFPFW_DL_DST) != 0 ) ? OFPFW_DL_SRC : 0;
945 ret.wildcards |= ((this.wildcards & OFPFW_DL_SRC) != 0 ) ? OFPFW_DL_DST : 0;
946 ret.wildcards |= (((this.wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT) << OFPFW_NW_SRC_SHIFT);
947 ret.wildcards |= (((this.wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT) << OFPFW_NW_DST_SHIFT);
948 ret.wildcards |= ((this.wildcards & OFPFW_TP_DST) != 0 ) ? OFPFW_TP_SRC : 0;
949 ret.wildcards |= ((this.wildcards & OFPFW_TP_SRC) != 0 ) ? OFPFW_TP_DST : 0;
955 * Check whether this match subsumes another match.
957 * This match subsumes another match if each field in this
960 * <li> exactly matches the corresponding field in the other match
961 * <li> the field is wildcarded in this object
963 * Note: The network source and destination wildcards must have fewer
964 * or the same number of bits wildcarded in this object as the other.
966 * @param match match used for comparison when checking subsumes
967 * @return boolean indicating whether this match subsumes another match
969 public boolean subsumes(OFMatch match) {
971 if ((wildcards & OFPFW_IN_PORT) == 0) {
972 if (inputPort != match.inputPort) {
978 if ((wildcards & OFPFW_DL_DST) == 0) {
979 if (!Arrays.equals(dataLayerDestination, match.dataLayerDestination)) {
983 if ((wildcards & OFPFW_DL_SRC) == 0) {
984 if (!Arrays.equals(dataLayerSource, match.dataLayerSource)) {
988 if ((wildcards & OFPFW_DL_TYPE) == 0) {
989 if (dataLayerType != match.dataLayerType) {
993 if ((wildcards & OFPFW_DL_VLAN) == 0) {
994 if (dataLayerVirtualLan!= match.dataLayerVirtualLan) {
998 if ((wildcards & OFPFW_DL_VLAN_PCP) == 0) {
999 if (dataLayerVirtualLanPriorityCodePoint != match.dataLayerVirtualLanPriorityCodePoint) {
1005 int maskLen = getNetworkDestinationMaskLen();
1006 if (maskLen > match.getNetworkDestinationMaskLen()) {
1009 int mask = (maskLen == 0) ? 0 : (0xffffffff << (32 - maskLen));
1010 if ((networkDestination & mask) != (match.networkDestination & mask)) {
1013 maskLen = getNetworkSourceMaskLen();
1014 if (maskLen > match.getNetworkSourceMaskLen()) {
1017 mask = (maskLen == 0) ? 0 : (0xffffffff << (32 - maskLen));
1018 if ((networkSource & mask) != (match.networkSource & mask)) {
1021 if ((wildcards & OFPFW_NW_PROTO) == 0) {
1022 if (networkProtocol != match.networkProtocol) {
1026 if ((wildcards & OFPFW_NW_TOS) == 0) {
1027 if (networkTypeOfService != match.networkTypeOfService) {
1033 if ((wildcards & OFPFW_TP_DST) == 0) {
1034 if (transportDestination != match.transportDestination) {
1038 if ((wildcards & OFPFW_TP_SRC) == 0) {
1039 if (transportSource != match.transportSource) {