Merge "Bug 6110: Fixed bugs in statistics manager due to race condition." into stable...
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / util / MatchComparatorHelper.java
index 16684efa9162e02b855c13856711883340c80fff..c6b317404245dbd8d1b2d40b34189895a2a05ffe 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -59,6 +59,7 @@ public class MatchComparatorHelper {
     private static final int IPV4_ADDRESS_LENGTH = 32;
     private static final int IPV6_ADDRESS_LENGTH = 128;
     private static final int BYTE_SIZE = 8;
+    private static final String NO_ETH_MASK = "ff:ff:ff:ff:ff:ff";
 
     /*
      * Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in any case
@@ -102,7 +103,7 @@ public class MatchComparatorHelper {
         } else {
             verdict = macAddressEquals(statsEthernetMatchFields.getAddress(), storedEthernetMatchFields.getAddress());
             if (verdict) {
-                verdict = macAddressEquals(statsEthernetMatchFields.getMask(), storedEthernetMatchFields.getMask());
+                verdict = macAddressMaskEquals(statsEthernetMatchFields.getMask(), storedEthernetMatchFields.getMask());
             }
         }
         return verdict;
@@ -119,6 +120,22 @@ public class MatchComparatorHelper {
         return verdict;
     }
 
+    static boolean macAddressMaskEquals(final MacAddress statsMacAddressMask, final MacAddress storedMacAddressMask) {
+        boolean verdict = true;
+        //User sent the mask with all bit set, which actually means no mask. Switch might just ignore it.
+        if(statsMacAddressMask == null && storedMacAddressMask != null &&
+                storedMacAddressMask.getValue().equalsIgnoreCase(NO_ETH_MASK)) {
+            return verdict;
+        }
+        final Boolean checkNullValues = checkNullValues(statsMacAddressMask, storedMacAddressMask);
+        if (checkNullValues != null) {
+            verdict = checkNullValues;
+        } else {
+            verdict = statsMacAddressMask.getValue().equalsIgnoreCase(storedMacAddressMask.getValue());
+        }
+        return verdict;
+    }
+
     @VisibleForTesting
     static boolean layer3MatchEquals(final Layer3Match statsLayer3Match, final Layer3Match storedLayer3Match) {
         boolean verdict = true;
@@ -212,6 +229,35 @@ public class MatchComparatorHelper {
                 }
                 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, statsIpv4Match.getIpv4Source());
             }
+        } else if (statsLayer3Match instanceof Ipv4MatchArbitraryBitMask && storedLayer3Match instanceof Ipv4Match) {
+            // Here stored netmask is an instance of Ipv4MatchArbitraryBitMask, when it is pushed in to switch
+            // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes)
+            // Eg:- stats src/dest -> 1.1.1.0/24  stored src/dest -> 1.1.1.0/255.255.255.0
+            final Ipv4Match storedIpv4Match = (Ipv4Match) storedLayer3Match;
+            final Ipv4MatchArbitraryBitMask statsIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) statsLayer3Match;
+            if (statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
+                Ipv4Prefix ipv4PrefixDestination;
+                if (statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask() != null) {
+                    byte[] destByteMask = convertArbitraryMaskToByteArray(statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
+                    ipv4PrefixDestination = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), destByteMask);
+                } else {
+                    ipv4PrefixDestination = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask());
+                }
+                verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixDestination, storedIpv4Match.getIpv4Destination());
+                if (verdict == false) {
+                    return verdict;
+                }
+            }
+            if (statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
+                Ipv4Prefix ipv4PrefixSource;
+                if (statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask() != null) {
+                    byte[] srcByteMask = convertArbitraryMaskToByteArray(statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
+                    ipv4PrefixSource = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask(), srcByteMask);
+                } else {
+                    ipv4PrefixSource = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask());
+                }
+                verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, storedIpv4Match.getIpv4Source());
+            }
         } else if (statsLayer3Match instanceof Ipv6MatchArbitraryBitMask && storedLayer3Match instanceof Ipv6MatchArbitraryBitMask) {
             // At this moment storedIpv6MatchArbitraryBitMask & statsIpv6MatchArbitraryBitMask will always have non null arbitrary masks.
             // In case of no / null arbitrary mask, statsLayer3Match will be an instance of Ipv6Match.
@@ -292,6 +338,36 @@ public class MatchComparatorHelper {
                 }
                 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixSource, statsIpv6Match.getIpv6Source());
             }
+        } else if (statsLayer3Match instanceof Ipv6MatchArbitraryBitMask && storedLayer3Match instanceof Ipv6Match) {
+            // Here stored netmask is an instance of Ipv6MatchArbitraryBitMask, when it is pushed in to switch
+            // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes)
+            // Eg:- stats src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/124
+            // stored src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFF0
+            final Ipv6Match storedIpv6Match = (Ipv6Match) storedLayer3Match;
+            final Ipv6MatchArbitraryBitMask statsIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) statsLayer3Match;
+            if (statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) {
+                Ipv6Prefix ipv6PrefixDestination;
+                if (statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask() != null) {
+                    byte[] destByteMask = convertIpv6ArbitraryMaskToByteArray(statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
+                    ipv6PrefixDestination = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(), destByteMask);
+                } else {
+                    ipv6PrefixDestination = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask());
+                }
+                verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixDestination, storedIpv6Match.getIpv6Destination());
+                if (verdict == false) {
+                    return verdict;
+                }
+            }
+            if (statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) {
+                Ipv6Prefix ipv6PrefixSource;
+                if (statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask() != null) {
+                    byte[] srcByteMask = convertIpv6ArbitraryMaskToByteArray(statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
+                    ipv6PrefixSource = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask(), srcByteMask);
+                } else {
+                    ipv6PrefixSource = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask());
+                }
+                verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixSource, storedIpv6Match.getIpv6Source());
+            }
         } else if (statsLayer3Match instanceof ArpMatch && storedLayer3Match instanceof ArpMatch) {
             verdict = arpMatchEquals((ArpMatch)statsLayer3Match, (ArpMatch)storedLayer3Match);
         } else {