deviceCtx should not be used where is not needed
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / util / HashUtil.java
index 23bd07a030143284c6c332c297046e37f738678e..14b9e3b97c4d46bdebc52f74594d0b900052e95b 100644 (file)
@@ -10,8 +10,12 @@ package org.opendaylight.openflowplugin.impl.util;
 
 import java.math.BigInteger;
 import java.util.StringTokenizer;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
+import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion;
 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.inet.types.rev100924.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
@@ -54,14 +58,16 @@ public final class HashUtil {
     private static final Logger LOG = LoggerFactory.getLogger(HashUtil.class);
     private static final int BASE_16 = 16;
     private static final int BASE_10 = 10;
+    private static final long IPV6_TOKENS_COUNT = 8;
+    public static final String IPV6_TOKEN = ":0000";
 
     private HashUtil() {
 
         throw new IllegalStateException("This class should not be instantiated.");
     }
 
-    public static int calculateEthernetMatchHash(EthernetMatch ethernetMatch) {
-        int hash = 0;
+    public static long calculateEthernetMatchHash(EthernetMatch ethernetMatch) {
+        long hash = 0;
 
         EthernetType ethernetType = ethernetMatch.getEthernetType();
         if (null != ethernetType) {
@@ -81,33 +87,32 @@ public final class HashUtil {
         return hash;
     }
 
-    public static int calculateEthenetSourceHash(EthernetSource ethernetSource) {
-        int hash = calculateMacAddressHash(ethernetSource.getAddress());
+    public static long calculateEthenetSourceHash(EthernetSource ethernetSource) {
+        long hash = calculateMacAddressHash(ethernetSource.getAddress());
         hash += calculateMacAddressHash(ethernetSource.getMask());
         return hash;
     }
 
-    public static int calculateEthernetDestinationHash(EthernetDestination ethernetDestination) {
-        int hash = calculateMacAddressHash(ethernetDestination.getAddress());
+    public static long calculateEthernetDestinationHash(EthernetDestination ethernetDestination) {
+        long hash = calculateMacAddressHash(ethernetDestination.getAddress());
         hash += calculateMacAddressHash(ethernetDestination.getMask());
         return hash;
     }
 
-    public static int calculateMacAddressHash(MacAddress macAddress) {
+    public static long calculateMacAddressHash(MacAddress macAddress) {
 
-        int hash = 0;
+        long hash = 0;
         if (null != macAddress) {
             StringTokenizer stringTokenizer = new StringTokenizer(macAddress.getValue(), ":");
-            hash = parseTokens(stringTokenizer, BASE_16);
+            hash = parseTokens(stringTokenizer, BASE_16, 8);
         }
-        LOG.trace("Calculated hash {} for mac {}", hash, macAddress);
         return hash;
     }
 
-    public static int calculateMatchHash(final Match match) {
-        int hash = 0;
-        int subHash = 0;
-        int base = 0;
+    public static long calculateMatchHash(final Match match, short version) {
+        long hash = 0;
+        long subHash = 0;
+        long base = 0;
         if (null != match) {
             if (null != match.getEthernetMatch()) {
                 hash = 1 << base;
@@ -126,12 +131,12 @@ public final class HashUtil {
             base++;
             if (null != match.getInPhyPort()) {
                 hash = 1 << base;
-                subHash += calculateNodeConnectorIdHash(match.getInPhyPort());
+                subHash += calculateNodeConnectorIdHash(match.getInPhyPort(), version);
             }
             base++;
             if (null != match.getInPort()) {
                 hash = 1 << base;
-                subHash += calculateNodeConnectorIdHash(match.getInPort());
+                subHash += calculateNodeConnectorIdHash(match.getInPort(), version);
             }
             base++;
             if (null != match.getIpMatch()) {
@@ -182,8 +187,8 @@ public final class HashUtil {
         return hash + subHash;
     }
 
-    private static int calculateTunnelHash(final Tunnel tunnel) {
-        int hash = 0;
+    private static long calculateTunnelHash(final Tunnel tunnel) {
+        long hash = 0;
         BigInteger tunnelId = tunnel.getTunnelId();
         if (null != tunnelId) {
             hash += tunnelId.intValue();
@@ -196,8 +201,8 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateVlanMatchHash(final VlanMatch vlanMatch) {
-        int hash = 0;
+    private static long calculateVlanMatchHash(final VlanMatch vlanMatch) {
+        long hash = 0;
 
         VlanId vlanId = vlanMatch.getVlanId();
         if (null != vlanId) {
@@ -212,13 +217,13 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateTcpFlagMatch(final TcpFlagMatch tcpFlagMatch) {
-        int hash = tcpFlagMatch.getTcpFlag().intValue();
+    private static long calculateTcpFlagMatch(final TcpFlagMatch tcpFlagMatch) {
+        long hash = tcpFlagMatch.getTcpFlag().intValue();
         return hash;
     }
 
-    private static int calculateProtocolMatchFieldsHash(final ProtocolMatchFields protocolMatchFields) {
-        int hash = 0;
+    private static long calculateProtocolMatchFieldsHash(final ProtocolMatchFields protocolMatchFields) {
+        long hash = 0;
         Short mplsBos = protocolMatchFields.getMplsBos();
         if (null != mplsBos) {
             hash += mplsBos.intValue();
@@ -243,20 +248,22 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateMetadataHash(final Metadata metadata) {
-        int hash = metadata.getMetadata().intValue();
-        hash += metadata.getMetadataMask().intValue();
+    private static long calculateMetadataHash(final Metadata metadata) {
+        long hash = metadata.getMetadata().intValue();
+        if (null != metadata.getMetadataMask()) {
+            hash += metadata.getMetadataMask().intValue();
+        }
         return hash;
     }
 
-    private static int calculateIcmpv6MatchHash(final Icmpv6Match icmpv6Match) {
-        int hash = icmpv6Match.getIcmpv6Code().intValue();
+    private static long calculateIcmpv6MatchHash(final Icmpv6Match icmpv6Match) {
+        long hash = icmpv6Match.getIcmpv6Code().intValue();
         hash += icmpv6Match.getIcmpv6Type().intValue();
         return hash;
     }
 
-    private static int calculateLayer4MatchHash(final Layer4Match layer4Match) {
-        int hash = 0;
+    private static long calculateLayer4MatchHash(final Layer4Match layer4Match) {
+        long hash = 0;
         if (layer4Match instanceof SctpMatch) {
             hash += calculateSctpMatchHash((SctpMatch) layer4Match);
         }
@@ -270,13 +277,13 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateUdpMatchHash(final UdpMatch layer4Match) {
-        int hash = 0;
+    private static long calculateUdpMatchHash(final UdpMatch layer4Match) {
+        long hash = 0;
         return hash;
     }
 
-    private static int calculateTcpMatchHash(final TcpMatch layer4Match) {
-        int hash = 0;
+    private static long calculateTcpMatchHash(final TcpMatch layer4Match) {
+        long hash = 0;
         PortNumber sourcePort = layer4Match.getTcpSourcePort();
         if (null != sourcePort) {
             hash += sourcePort.getValue().intValue();
@@ -289,8 +296,8 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateSctpMatchHash(final SctpMatch layer4Match) {
-        int hash = 0;
+    private static long calculateSctpMatchHash(final SctpMatch layer4Match) {
+        long hash = 0;
 
         PortNumber portNumber = layer4Match.getSctpDestinationPort();
         if (null != portNumber) {
@@ -304,8 +311,8 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateLayer3MatchHash(final Layer3Match layer3Match) {
-        int hash = 0;
+    private static long calculateLayer3MatchHash(final Layer3Match layer3Match) {
+        long hash = 0;
         if (layer3Match instanceof ArpMatch) {
             hash += calculateArpMatchHash((ArpMatch) layer3Match);
         }
@@ -322,55 +329,130 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateTunnelIpv4Hash(final TunnelIpv4Match layer3Match) {
+    private static long calculateTunnelIpv4Hash(final TunnelIpv4Match layer3Match) {
         Ipv4Prefix tunnelIpv4Destination = layer3Match.getTunnelIpv4Destination();
-        int hash = calculateIpv4PrefixHash(tunnelIpv4Destination);
+        long hash = calculateIpv4PrefixHash(tunnelIpv4Destination);
         Ipv4Prefix tunnelIpv4Source = layer3Match.getTunnelIpv4Source();
         hash += calculateIpv4PrefixHash(tunnelIpv4Source);
         return hash;
     }
 
-    private static int calculateIpv6MatchHash(final Ipv6Match layer3Match) {
-        int hash = 0;
+    private static long calculateIpv6MatchHash(final Ipv6Match layer3Match) {
+        long hash = 0;
         Ipv6Prefix ipv6Destination = layer3Match.getIpv6Destination();
         if (null != ipv6Destination) {
             hash += calculateIpv6PrefixHash(ipv6Destination);
         }
+
+        if (null != layer3Match.getIpv6Source()) {
+            hash += calculateIpv6PrefixHash(layer3Match.getIpv6Source());
+        }
+
+        if (null != layer3Match.getIpv6ExtHeader()) {
+            hash += layer3Match.getIpv6ExtHeader().getIpv6Exthdr();
+            hash += layer3Match.getIpv6ExtHeader().getIpv6ExthdrMask();
+        }
+
+        if (null != layer3Match.getIpv6NdSll()) {
+            hash += calculateMacAddressHash(layer3Match.getIpv6NdSll());
+        }
+        if (null != layer3Match.getIpv6NdTll()) {
+            hash += calculateMacAddressHash(layer3Match.getIpv6NdTll());
+        }
+        if (null != layer3Match.getIpv6NdTarget()) {
+            hash += calculateIpv6AddressHash(layer3Match.getIpv6NdTarget());
+        }
         return hash;
     }
 
 
-    public static int calculateIpv6PrefixHash(final Ipv6Prefix ipv6Prefix) {
-        StringTokenizer stringTokenizer = new StringTokenizer(ipv6Prefix.getValue(), ":");
-        int hash = parseTokens(stringTokenizer, BASE_16);
+    public static long calculateIpv6PrefixHash(final Ipv6Prefix ipv6Prefix) {
+
+        StringTokenizer stringTokenizer = getStringTokenizerWithFullAddressString(ipv6Prefix.getValue());
+
+        long hash = parseTokens(stringTokenizer, BASE_16, 16);
         return hash;
     }
 
-    private static int parseTokens(final StringTokenizer stringTokenizer, int base) {
-        return parseTokens(stringTokenizer, 0, base);
+    public static long calculateIpv6AddressHash(final Ipv6Address ipv6Address) {
+
+        StringTokenizer stringTokenizer = getStringTokenizerWithFullAddressString(ipv6Address.getValue());
+
+        long hash = parseTokens(stringTokenizer, BASE_16, 16);
+        return hash;
     }
 
-    private static int parseTokens(final StringTokenizer stringTokenizer, int stopper, int base) {
-        int hash = 0;
+    private static StringTokenizer getStringTokenizerWithFullAddressString(String value) {
+        String ipv6Value = value.replace("::", ":0000:");
+        StringTokenizer stringTokenizer = new StringTokenizer(ipv6Value, ":");
+
+        long delta = IPV6_TOKENS_COUNT - stringTokenizer.countTokens();
+
+        StringBuffer additions = new StringBuffer();
+
+        if (delta > 0) {
+            while (delta > 0) {
+                additions.append(IPV6_TOKEN);
+                delta--;
+            }
+            if (ipv6Value.contains("/")) {
+                ipv6Value = ipv6Value.replace("/", additions.toString() + "/");
+            } else {
+                ipv6Value += additions.toString();
+            }
+            stringTokenizer = new StringTokenizer(ipv6Value, ":");
+        }
+        return stringTokenizer;
+    }
+
+    private static long calculateStopperBasedOnMaskValue(final Ipv6Prefix ipv6Prefix, long bitsBase) {
+        double maskValue = extractMask(ipv6Prefix);
+        double bitCount = maskValue / bitsBase;
+        return (int) Math.ceil(bitCount);
+    }
+
+    private static long extractMask(final Ipv6Prefix ipv6Prefix) {
+        StringTokenizer maskTokenizer = new StringTokenizer(ipv6Prefix.getValue(), "/");
+        long mask = 0;
+        if (maskTokenizer.countTokens() > 1) {
+            maskTokenizer.nextToken();
+            mask = Integer.parseInt(maskTokenizer.nextToken());
+        }
+        return mask;
+    }
+
+    private static long parseTokens(final StringTokenizer stringTokenizer, int base, int bitShift) {
+        return parseTokens(stringTokenizer, 0, base, bitShift);
+    }
+
+    private static long parseTokens(final StringTokenizer stringTokenizer, long stopper, int base, int bitShift) {
+        long hash = 0;
         if (stringTokenizer.countTokens() > 0) {
-            int step = 0;
+            long step = 0;
             while (stringTokenizer.hasMoreTokens()) {
+                String token = stringTokenizer.nextToken();
                 step++;
-                try {
-                    hash = hash ^ ((Integer.parseInt(stringTokenizer.nextToken(), base) * step) + step);
-                } catch (NumberFormatException nfe) {
-                    LOG.trace("Skipping empty token.");
+
+                if (token.equals("")) {
+                    token = "0";
                 }
-                if (stopper > 0 && step == stopper) {
-                    break;
+
+                if (token.contains("/")) {
+                    StringTokenizer tokenizer = new StringTokenizer(token, "/");
+                    hash += parseTokens(tokenizer, stopper, base, bitShift);
+                } else {
+                    hash += Long.parseLong(token, base) << (bitShift * step);
+                    if (stopper > 0 && step == stopper) {
+                        break;
+                    }
                 }
             }
         }
         return hash;
     }
 
-    private static int calculateIpv4MatchHash(final Ipv4Match layer3Match) {
-        int hash = 0;
+    private static long calculateIpv4MatchHash(final Ipv4Match layer3Match) {
+        long hash = 0;
         Ipv4Prefix ipv4Destination = layer3Match.getIpv4Destination();
         if (null != ipv4Destination) {
             hash += calculateIpv4PrefixHash(ipv4Destination);
@@ -386,8 +468,8 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateArpMatchHash(final ArpMatch layer3Match) {
-        int hash = 0;
+    private static long calculateArpMatchHash(final ArpMatch layer3Match) {
+        long hash = 0;
         Integer arpOp = layer3Match.getArpOp();
         if (null != arpOp) {
             hash += arpOp.intValue();
@@ -417,13 +499,13 @@ public final class HashUtil {
         return hash;
     }
 
-    public static int calculateIpv4PrefixHash(final Ipv4Prefix ipv4Prefix) {
-        int hash = 0;
+    public static long calculateIpv4PrefixHash(final Ipv4Prefix ipv4Prefix) {
+        long hash = 0;
         StringTokenizer prefixAsArray = new StringTokenizer(ipv4Prefix.getValue(), "/");
         if (prefixAsArray.countTokens() == 2) {
             String address = prefixAsArray.nextToken();
-            Integer mask = Integer.parseInt(prefixAsArray.nextToken());
-            int numberOfAddressPartsToUse = (int) Math.ceil(mask.doubleValue() / 8);
+            Long mask = Long.parseLong(prefixAsArray.nextToken());
+            long numberOfAddressPartsToUse = (int) Math.ceil(mask.doubleValue() / 8);
             hash += calculateIpAdressHash(address, numberOfAddressPartsToUse, BASE_10);
             hash += mask.shortValue();
         }
@@ -431,14 +513,14 @@ public final class HashUtil {
     }
 
 
-    private static int calculateIpAdressHash(final String address, int numberOfParts, int base) {
+    private static long calculateIpAdressHash(final String address, long numberOfParts, int base) {
         StringTokenizer stringTokenizer = new StringTokenizer(address, ".");
-        int hash = parseTokens(stringTokenizer, numberOfParts, base);
+        long hash = parseTokens(stringTokenizer, numberOfParts, base, 8);
         return hash;
     }
 
-    private static int calculateIpMatchHash(final IpMatch ipMatch) {
-        int hash = 0;
+    private static long calculateIpMatchHash(final IpMatch ipMatch) {
+        long hash = 0;
         Short ipEcn = ipMatch.getIpEcn();
         if (null != ipEcn) {
             hash += ipEcn.shortValue();
@@ -460,14 +542,15 @@ public final class HashUtil {
         return hash;
     }
 
-    private static int calculateNodeConnectorIdHash(final NodeConnectorId inPhyPort) {
-        int hash = 0;
-        hash += Integer.valueOf(inPhyPort.getValue());
+    private static long calculateNodeConnectorIdHash(final NodeConnectorId inPhyPort, short version) {
+        long hash = 0;
+        Long portFromLogicalName = OpenflowPortsUtil.getPortFromLogicalName(OpenflowVersion.get(version), inPhyPort.getValue());
+        hash += portFromLogicalName.intValue();
         return hash;
     }
 
-    private static int calculateIcmpV6MatchHash(final Icmpv6Match icmpv6Match) {
-        int hash = 0;
+    private static long calculateIcmpV6MatchHash(final Icmpv6Match icmpv6Match) {
+        long hash = 0;
         if (null != icmpv6Match.getIcmpv6Code()) {
             hash += icmpv6Match.getIcmpv6Code();
         }
@@ -477,8 +560,8 @@ public final class HashUtil {
         return hash;
     }
 
-    public static int calculateIcmpV4MatchHash(final Icmpv4Match icmpv4Match) {
-        int hash = 0;
+    public static long calculateIcmpV4MatchHash(final Icmpv4Match icmpv4Match) {
+        long hash = 0;
         if (null != icmpv4Match.getIcmpv4Code()) {
             hash += icmpv4Match.getIcmpv4Code();
         }