Merge "Bug 1088 - flow id in operational not matched; after removal not removed compl...
authorEd Warnicke <eaw@cisco.com>
Thu, 28 Aug 2014 11:30:18 +0000 (11:30 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 28 Aug 2014 11:30:18 +0000 (11:30 +0000)
opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java
opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java

index 2b67edfd9d318d29cbd3508c17a1e8bafd9f4a70..f3dac826e8ad609d39e024cbc7e46239934da035 100644 (file)
@@ -12,8 +12,11 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
 import org.slf4j.Logger;
@@ -100,7 +103,7 @@ final class FlowComparator {
             if (statsFlow.getEthernetMatch() != null) {
                 return false;
             }
-        } else if(!storedFlow.getEthernetMatch().equals(statsFlow.getEthernetMatch())) {
+        } else if(!ethernetMatchEquals(statsFlow.getEthernetMatch(),storedFlow.getEthernetMatch())) {
             return false;
         }
         if (storedFlow.getIcmpv4Match()== null) {
@@ -183,6 +186,67 @@ final class FlowComparator {
         return true;
     }
 
+    /*
+     * Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in
+     * any case (upper or lower or mix). Ethernet Match which controller receives from switch is always
+     * an upper case string. Default EthernetMatch equals doesn't use equalsIgnoreCase() and hence it fails.
+     * E.g User provided mac address string in flow match is aa:bb:cc:dd:ee:ff and when controller fetch
+     * statistic data, openflow driver library returns AA:BB:CC:DD:EE:FF and default eqauls fails here.
+     */
+    @VisibleForTesting
+    static boolean ethernetMatchEquals(EthernetMatch statsEthernetMatch, EthernetMatch storedEthernetMatch){
+        boolean verdict = true;
+        Boolean checkNullValues = checkNullValues(statsEthernetMatch, storedEthernetMatch);
+        if (checkNullValues != null) {
+            verdict = checkNullValues;
+        } else {
+            if(verdict){
+                verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetSource(),storedEthernetMatch.getEthernetSource());
+            }
+            if(verdict){
+                verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetDestination(),storedEthernetMatch.getEthernetDestination());
+            }
+            if(verdict){
+                if(statsEthernetMatch.getEthernetType() == null){
+                    if(storedEthernetMatch.getEthernetType() != null){
+                        verdict = false;
+                    }
+                }else{
+                    verdict = statsEthernetMatch.getEthernetType().equals(storedEthernetMatch.getEthernetType());
+                }
+            }
+        }
+        return verdict;
+    }
+
+    private static boolean ethernetMatchFieldsEquals(MacAddressFilter statsEthernetMatchFields,
+                                                        MacAddressFilter storedEthernetMatchFields){
+        boolean verdict = true;
+        Boolean checkNullValues = checkNullValues(statsEthernetMatchFields, storedEthernetMatchFields);
+        if (checkNullValues != null) {
+            verdict = checkNullValues;
+        } else {
+            if(verdict){
+                verdict = macAddressEquals(statsEthernetMatchFields.getAddress(),storedEthernetMatchFields.getAddress());
+            }
+            if(verdict){
+                verdict = macAddressEquals(statsEthernetMatchFields.getMask(),storedEthernetMatchFields.getMask());
+            }
+        }
+        return verdict;
+    }
+
+    private static boolean macAddressEquals(MacAddress statsMacAddress, MacAddress storedMacAddress){
+        boolean verdict = true;
+        Boolean checkNullValues = checkNullValues(statsMacAddress, storedMacAddress);
+        if (checkNullValues != null) {
+            verdict = checkNullValues;
+        } else {
+            verdict = statsMacAddress.getValue().equalsIgnoreCase(storedMacAddress.getValue());
+        }
+        return verdict;
+    }
+
     @VisibleForTesting
     static boolean layer3MatchEquals(Layer3Match statsLayer3Match, Layer3Match storedLayer3Match){
         boolean verdict = true;
index bf523a433bf8423a3badc399b77386296f152ca7..a687b1f28049bf7cc8b6220fb97c5d4540dac9d3 100644 (file)
@@ -11,6 +11,12 @@ package org.opendaylight.controller.md.statistics.manager;
 import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.slf4j.Logger;
@@ -111,5 +117,96 @@ public class StatisticsUpdateCommiterTest {
 
         return ipv4MatchBuilder.build();
     }
+    /**
+     * Test method for {@link org.opendaylight.controller.md.statistics.manager.FlowComparator#ethernetMatchEquals(EthernetMatch, EthernetMatch)
+     */
+    @Test
+    public void testEthernetMatchEquals() {
+        String[][][] ethernetMatchSeeds = new String[][][] {
+                {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}},
+                {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:bc:cd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}},
+                {{"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"AA:BB:CC:DD:EE:FF", "ff:ff:ff:ff:ff:ff","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:cc:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff","0800"}, {"aa:bb:cc:dd:ee:ff", "FF:FF:FF:FF:FF:FF","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ee:ee:ee","0800"}, {"aa:bb:cc:dd:ee:ff", "FF:FF:FF:FF:FF:FF","0800"}},
+
+                {{"AA:BB:CC:dd:ee:ff", null,"0800"}, {"aa:bb:cc:dd:ee:ff", null,"0800"}},
+                {{"AA:BB:CC:dd:ee:ff", null,"0800"}, {"aa:bb:cc:dd:ee:ff", null,"0806"}},
+                {{"AA:BB:CC:dd:ee:ff", null,"0800"}, {"aa:bb:cc:dd:ee:ff", "FF:FF:FF:FF:FF:FF","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", null,"0800"}, {null, "FF:FF:FF:FF:FF:FF","0800"}},
+
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff",null}, {null, "FF:FF:FF:FF:FF:FF","0800"}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff",null}, {"aa:bb:cc:dd:ee:ff", "FF:FF:FF:FF:FF:FF",null}},
+                {{"AA:BB:CC:dd:ee:ff", "ff:ff:ff:ff:ff:ff",null}, {null, "FF:FF:FF:FF:FF:FF",null}},
+
+                {{null, null,null}, {null, null,"0800"}},
+                {{null, null,null}, {null, null,null}},
+        };
+
+        boolean[] matches = new boolean[] {
+                true,
+                false,
+                true,
+                true,
+                true,
+                false,
+
+                true,
+                false,
+                false,
+                false,
 
+                false,
+                true,
+                false,
+
+                false,
+                true
+        };
+
+        for (int i = 0; i < matches.length; i++) {
+            checkComparisonOfEthernetMatch(
+                    ethernetMatchSeeds[i][0][0], ethernetMatchSeeds[i][0][1],ethernetMatchSeeds[i][0][2],
+                    ethernetMatchSeeds[i][1][0], ethernetMatchSeeds[i][1][1],ethernetMatchSeeds[i][1][2],
+                    matches[i]);
+        }
+    }
+
+    /*
+     * @param ethernetMatch1
+     * @param ethernetMatch2
+     */
+    private static void checkComparisonOfEthernetMatch(String macAddress1, String macAddressMask1,String etherType1,
+            String macAddress2, String macAddressMask2,String etherType2, boolean expectedResult) {
+        EthernetMatch ethernetMatch1 = prepareEthernetMatch(macAddress1, macAddressMask1,etherType1);
+        EthernetMatch ethernetMatch2 = prepareEthernetMatch(macAddress2, macAddressMask2,etherType2);
+        boolean comparisonResult;
+        try {
+            comparisonResult = FlowComparator.ethernetMatchEquals(ethernetMatch1, ethernetMatch2);
+            Assert.assertEquals("failed to compare: "+ethernetMatch1+" vs. "+ethernetMatch2,
+                    expectedResult, comparisonResult);
+        } catch (Exception e) {
+            LOG.error("failed to compare: {} vs. {}", ethernetMatch1, ethernetMatch2, e);
+            Assert.fail(e.getMessage());
+        }
+    }
+
+    private static EthernetMatch prepareEthernetMatch(String macAddress, String macAddressMask, String etherType) {
+        EthernetMatchBuilder ethernetMatchBuilder = new EthernetMatchBuilder();
+        EthernetSourceBuilder ethernetSourceBuilder =  new EthernetSourceBuilder();
+        if (macAddress != null) {
+            ethernetSourceBuilder.setAddress(new MacAddress(macAddress));
+        }
+        if (macAddressMask != null) {
+            ethernetSourceBuilder.setMask(new MacAddress(macAddressMask));
+        }
+        if(etherType != null){
+            EthernetTypeBuilder ethernetType = new EthernetTypeBuilder();
+            ethernetType.setType(new EtherType(Long.parseLong(etherType,16)));
+            ethernetMatchBuilder.setEthernetType(ethernetType.build());
+        }
+        ethernetMatchBuilder.setEthernetSource(ethernetSourceBuilder.build());
+
+        return ethernetMatchBuilder.build();
+    }
 }