+ return !this.intersetcs(filter);
+ }
+
+ /**
+ * Merge the current Match fields with the fields of the filter Match. A
+ * check is first run to see if this Match is compatible with the filter
+ * Match. If it is not, the merge is not attempted.
+ *
+ * The result is the match object representing the intersection of the set
+ * of packets described by this match with the set of packets described by
+ * the filter match. If the intersection of the two sets is empty, the
+ * return match will be empty as well.
+ *
+ * @param filter
+ * the match with which attempting the merge
+ * @return a new Match object describing the set of packets represented by
+ * the intersection of this and the filter matches.
+ */
+ public Match mergeWithFilter(Match filter) {
+ return this.getIntersection(filter);
+ }
+
+ /**
+ * Return the match representing the intersection of the set of packets
+ * described by this match with the set of packets described by the other
+ * match. Such as m.intersect(m) == m and m.intersect(o) == o where o is an
+ * empty match.
+ *
+ * @param other
+ * the match with which computing the intersection
+ * @return a new Match object representing the intersection of the set of
+ * packets described by this match with the set of packets described
+ * by the other match.
+ */
+ public Match getIntersection(Match other) {
+ Match intersection = new Match();
+ if (this.intersetcs(other)) {
+ for (MatchType type : MatchType.values()) {
+ if (this.isAny(type) && other.isAny(type)) {
+ continue;
+ }
+ if (this.isAny(type)) {
+ intersection.setField(other.getField(type).clone());
+ continue;
+ } else if (other.isAny(type)) {
+ intersection.setField(this.getField(type).clone());
+ continue;
+ }
+ // Either they are equal or it is about IP address
+ switch (type) {
+ // When it is about IP address, take the wider prefix address between the twos
+ case NW_SRC:
+ case NW_DST:
+ MatchField thisField = this.getField(type);
+ MatchField otherField = other.getField(type);
+ InetAddress thisAddress = (InetAddress) thisField.getValue();
+ InetAddress otherAddress = (InetAddress) otherField.getValue();
+ InetAddress thisMask = (InetAddress) thisField.getMask();
+ InetAddress otherMask = (InetAddress) otherField.getMask();
+
+ int thisMaskLen = (thisMask == null) ? ((thisAddress instanceof Inet4Address) ? 32 : 128)
+ : NetUtils.getSubnetMaskLength(thisMask);
+ int otherMaskLen = (otherMask == null) ? ((otherAddress instanceof Inet4Address) ? 32 : 128)
+ : NetUtils.getSubnetMaskLength(otherMask);
+ if (otherMaskLen < thisMaskLen) {
+ intersection.setField(new MatchField(type, NetUtils.getSubnetPrefix(otherAddress, otherMaskLen), otherMask));
+ } else {
+ intersection.setField(new MatchField(type, NetUtils.getSubnetPrefix(thisAddress, thisMaskLen), thisMask));
+ }
+ break;
+ default:
+ // this and other match field are equal for this type, pick this match field
+ intersection.setField(this.getField(type).clone());
+ }
+ }
+ }
+ return intersection;
+ }
+
+ /**
+ * Checks whether the intersection of the set of packets described by this
+ * match with the set of packets described by the other match is non empty
+ *
+ * For example, if this match is: DL_SRC = 00:cc:bb:aa:11:22
+ *
+ * and the other match is: DL_TYPE = 0x800 NW_SRC = 1.2.3.4
+ *
+ * then their respective matching packets set intersection is non empty:
+ * DL_SRC = 00:cc:bb:aa:11:22 DL_TYPE = 0x800 NW_SRC = 1.2.3.4
+ *
+ * @param other
+ * the other match with which testing the intersection
+ * @return true if the intersection of the respective matching packets sets
+ * is non empty
+ */
+ public boolean intersetcs(Match other) {
+ if (this.getMatches() == 0 || other.getMatches() == 0) {
+ // No intersection with the empty set
+ return false;
+ }