From cb2ae2cbea6632ab6e80ad3673dadb6492802fb3 Mon Sep 17 00:00:00 2001 From: Asad Ahmed Date: Tue, 21 Jan 2014 23:00:19 -0800 Subject: [PATCH] Avoiding hash collisions of a match with its reverse Change-Id: I6b6942e90b85028af9ec98cb27cf17cd0377c033 Signed-off-by: Asad Ahmed --- .../opendaylight/controller/sal/match/Match.java | 16 ++++++++++------ .../controller/sal/match/MatchTest.java | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java index 2c3cfb8303..910695c1e9 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.TreeMap; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -444,13 +445,16 @@ public class Match implements Cloneable, Serializable { if (this.fields == null) { result = prime * result; } else { - int sum = 0; - for (MatchType field : this.fields.keySet()) { - MatchField f = this.fields.get(field); - sum = sum + ((field==null ? 0 : field.calculateConsistentHashCode()) ^ - (f==null ? 0 : f.hashCode())); + // use a tree map as the order of hashMap is not guaranteed. + // 2 Match objects with fields in different order are still equal. + // Hence the hashCode should be the same too. + TreeMap tm = new TreeMap(this.fields); + for (MatchType field : tm.keySet()) { + MatchField f = tm.get(field); + int fieldHashCode = (field==null ? 0 : field.calculateConsistentHashCode()) ^ + (f==null ? 0 : f.hashCode()); + result = prime * result + fieldHashCode; } - result = prime * result + sum; } result = prime * result + matches; return result; diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java index 30d49cfd9d..b88ae034d9 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/match/MatchTest.java @@ -337,6 +337,21 @@ public class MatchTest { Assert.assertTrue(match1.equals(match2)); } + @Test + public void testHashCodeWithReverseMatch() throws Exception { + InetAddress srcIP1 = InetAddress.getByName("1.1.1.1"); + InetAddress ipMask1 = InetAddress.getByName("255.255.255.255"); + InetAddress srcIP2 = InetAddress.getByName("2.2.2.2"); + InetAddress ipMask2 = InetAddress.getByName("255.255.255.255"); + MatchField field1 = new MatchField(MatchType.NW_SRC, srcIP1, ipMask1); + MatchField field2 = new MatchField(MatchType.NW_DST, srcIP2, ipMask2); + Match match1 = new Match(); + match1.setField(field1); + match1.setField(field2); + Match match2 = match1.reverse(); + Assert.assertFalse(match1.hashCode() == match2.hashCode()); + } + @Test public void testHashCode() throws Exception { byte srcMac1[] = { (byte) 0x12, (byte) 0x34, (byte) 0x56, (byte) 0x78, (byte) 0x9a, (byte) 0xbc }; -- 2.36.6