From: Ed Warnicke Date: Thu, 28 Aug 2014 11:30:18 +0000 (+0000) Subject: Merge "Bug 1088 - flow id in operational not matched; after removal not removed compl... X-Git-Tag: release/helium~187 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=413e4ecb09769460eaf740f067e06f198957ce13;hp=b9bd3ce8c3c0a5a73afe0301f455b7b7bf69eb3d Merge "Bug 1088 - flow id in operational not matched; after removal not removed completely Added comparator to compare ethernet address string in case (upper/lower case) agnostic way" --- diff --git a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java index 2b67edfd9d..f3dac826e8 100644 --- a/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java +++ b/opendaylight/md-sal/statistics-manager/src/main/java/org/opendaylight/controller/md/statistics/manager/FlowComparator.java @@ -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; diff --git a/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java b/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java index bf523a433b..a687b1f280 100644 --- a/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java +++ b/opendaylight/md-sal/statistics-manager/src/test/java/org/opendaylight/controller/md/statistics/manager/StatisticsUpdateCommiterTest.java @@ -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(); + } }