2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.impl.util;
11 import java.math.BigInteger;
12 import java.util.StringTokenizer;
13 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpVersion;
14 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddress;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestination;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSource;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4Match;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv6Match;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Metadata;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFields;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagMatch;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Tunnel;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.TunnelIpv4Match;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatch;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.protocol.match.fields.Pbb;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanId;
48 * Created by Martin Bobak <mbobak@cisco.com> on 8.4.2015.
50 public final class HashUtil {
52 private static final int BASE_16 = 16;
53 private static final int BASE_10 = 10;
57 throw new IllegalStateException("This class should not be instantiated.");
60 public static int calculateEthernetMatchHash(EthernetMatch ethernetMatch) {
63 EthernetType ethernetType = ethernetMatch.getEthernetType();
64 if (null != ethernetType) {
65 hash += ethernetType.getType().getValue();
68 EthernetDestination ethernetDestination = ethernetMatch.getEthernetDestination();
69 if (null != ethernetDestination) {
70 hash += calculateEthernetDestinationHash(ethernetDestination);
73 EthernetSource ethernetSource = ethernetMatch.getEthernetSource();
74 if (null != ethernetSource) {
75 hash += calculateEthenetSourceHash(ethernetSource);
81 public static int calculateEthenetSourceHash(EthernetSource ethernetSource) {
82 int hash = calculateMacAddressHash(ethernetSource.getAddress());
83 hash += calculateMacAddressHash(ethernetSource.getMask());
87 public static int calculateEthernetDestinationHash(EthernetDestination ethernetDestination) {
88 int hash = calculateMacAddressHash(ethernetDestination.getAddress());
89 hash += calculateMacAddressHash(ethernetDestination.getMask());
93 public static int calculateMacAddressHash(MacAddress macAddress) {
95 if (null != macAddress) {
96 StringTokenizer stringTokenizer = new StringTokenizer(macAddress.getValue(), ":");
97 hash = parseTokens(stringTokenizer, BASE_16);
102 public static int calculateMatchHash(final Match match) {
107 if (null != match.getEthernetMatch()) {
109 subHash += calculateEthernetMatchHash(match.getEthernetMatch());
112 if (null != match.getIcmpv4Match()) {
114 subHash += calculateIcmpV4MatchHash(match.getIcmpv4Match());
117 if (null != match.getIcmpv6Match()) {
119 subHash += calculateIcmpV6MatchHash(match.getIcmpv6Match());
122 if (null != match.getInPhyPort()) {
124 subHash += calculateNodeConnectorIdHash(match.getInPhyPort());
127 if (null != match.getInPort()) {
129 subHash += calculateNodeConnectorIdHash(match.getInPort());
132 if (null != match.getIpMatch()) {
134 subHash += calculateIpMatchHash(match.getIpMatch());
137 if (null != match.getLayer3Match()) {
139 subHash += calculateLayer3MatchHash(match.getLayer3Match());
142 if (null != match.getLayer4Match()) {
144 subHash += calculateLayer4MatchHash(match.getLayer4Match());
147 if (null != match.getIcmpv6Match()) {
149 subHash += calculateIcmpv6MatchHash(match.getIcmpv6Match());
152 if (null != match.getMetadata()) {
154 subHash += calculateMetadataHash(match.getMetadata());
157 if (null != match.getProtocolMatchFields()) {
159 subHash += calculateProtocolMatchFieldsHash(match.getProtocolMatchFields());
162 if (null != match.getTcpFlagMatch()) {
164 subHash += calculateTcpFlagMatch(match.getTcpFlagMatch());
167 if (null != match.getVlanMatch()) {
169 subHash += calculateVlanMatchHash(match.getVlanMatch());
172 if (null != match.getTunnel()) {
174 subHash += calculateTunnelHash(match.getTunnel());
177 return hash + subHash;
180 private static int calculateTunnelHash(final Tunnel tunnel) {
182 BigInteger tunnelId = tunnel.getTunnelId();
183 if (null != tunnelId) {
184 hash += tunnelId.intValue();
187 BigInteger tunnelMask = tunnel.getTunnelMask();
188 if (null != tunnelMask) {
189 hash += tunnelMask.intValue();
194 private static int calculateVlanMatchHash(final VlanMatch vlanMatch) {
197 VlanId vlanId = vlanMatch.getVlanId();
198 if (null != vlanId) {
199 hash += vlanId.getVlanId().getValue().intValue();
202 VlanPcp vlanPcp = vlanMatch.getVlanPcp();
203 if (null != vlanPcp) {
204 hash += vlanPcp.getValue().shortValue();
210 private static int calculateTcpFlagMatch(final TcpFlagMatch tcpFlagMatch) {
211 int hash = tcpFlagMatch.getTcpFlag().intValue();
215 private static int calculateProtocolMatchFieldsHash(final ProtocolMatchFields protocolMatchFields) {
217 Short mplsBos = protocolMatchFields.getMplsBos();
218 if (null != mplsBos) {
219 hash += mplsBos.intValue();
221 Short mplsTc = protocolMatchFields.getMplsTc();
222 if (null != mplsTc) {
223 hash += mplsTc.intValue();
225 Pbb pbb = protocolMatchFields.getPbb();
227 if (null != pbb.getPbbIsid()) {
228 hash += pbb.getPbbIsid().intValue();
230 if (null != pbb.getPbbMask()) {
231 hash += pbb.getPbbMask().intValue();
234 Long mplsLabel = protocolMatchFields.getMplsLabel();
235 if (null != mplsLabel) {
236 hash += mplsLabel.intValue();
241 private static int calculateMetadataHash(final Metadata metadata) {
242 int hash = metadata.getMetadata().intValue();
243 hash += metadata.getMetadataMask().intValue();
247 private static int calculateIcmpv6MatchHash(final Icmpv6Match icmpv6Match) {
248 int hash = icmpv6Match.getIcmpv6Code().intValue();
249 hash += icmpv6Match.getIcmpv6Type().intValue();
253 private static int calculateLayer4MatchHash(final Layer4Match layer4Match) {
255 if (layer4Match instanceof SctpMatch) {
256 hash += calculateSctpMatchHash((SctpMatch) layer4Match);
259 if (layer4Match instanceof TcpMatch) {
260 hash += calculateTcpMatchHash((TcpMatch) layer4Match);
262 if (layer4Match instanceof UdpMatch) {
263 hash += calculateUdpMatchHash((UdpMatch) layer4Match);
268 private static int calculateUdpMatchHash(final UdpMatch layer4Match) {
273 private static int calculateTcpMatchHash(final TcpMatch layer4Match) {
275 PortNumber sourcePort = layer4Match.getTcpSourcePort();
276 if (null != sourcePort) {
277 hash += sourcePort.getValue().intValue();
280 PortNumber destinationPort = layer4Match.getTcpDestinationPort();
281 if (null != destinationPort) {
282 hash += destinationPort.getValue().intValue();
287 private static int calculateSctpMatchHash(final SctpMatch layer4Match) {
290 PortNumber portNumber = layer4Match.getSctpDestinationPort();
291 if (null != portNumber) {
292 hash += portNumber.getValue().intValue();
295 PortNumber sourcePort = layer4Match.getSctpSourcePort();
296 if (null != sourcePort) {
297 hash += sourcePort.getValue().intValue();
302 private static int calculateLayer3MatchHash(final Layer3Match layer3Match) {
304 if (layer3Match instanceof ArpMatch) {
305 hash += calculateArpMatchHash((ArpMatch) layer3Match);
307 if (layer3Match instanceof Ipv4Match) {
308 hash += calculateIpv4MatchHash((Ipv4Match) layer3Match);
310 if (layer3Match instanceof Ipv6Match) {
311 hash += calculateIpv6MatchHash((Ipv6Match) layer3Match);
314 if (layer3Match instanceof TunnelIpv4Match) {
315 hash += calculateTunnelIpv4Hash((TunnelIpv4Match) layer3Match);
320 private static int calculateTunnelIpv4Hash(final TunnelIpv4Match layer3Match) {
321 Ipv4Prefix tunnelIpv4Destination = layer3Match.getTunnelIpv4Destination();
322 int hash = calculateIpv4PrefixHash(tunnelIpv4Destination);
323 Ipv4Prefix tunnelIpv4Source = layer3Match.getTunnelIpv4Source();
324 hash += calculateIpv4PrefixHash(tunnelIpv4Source);
328 private static int calculateIpv6MatchHash(final Ipv6Match layer3Match) {
330 Ipv6Prefix ipv6Destination = layer3Match.getIpv6Destination();
331 if (null != ipv6Destination) {
332 hash += calculateIpv6PrefixHash(ipv6Destination);
338 public static int calculateIpv6PrefixHash(final Ipv6Prefix ipv6Prefix) {
339 StringTokenizer stringTokenizer = new StringTokenizer(ipv6Prefix.getValue(), ":");
340 int hash = parseTokens(stringTokenizer, BASE_16);
344 private static int parseTokens(final StringTokenizer stringTokenizer, int base) {
345 return parseTokens(stringTokenizer, 0, base);
348 private static int parseTokens(final StringTokenizer stringTokenizer, int stopper, int base) {
350 if (stringTokenizer.countTokens() > 0) {
352 while (stringTokenizer.hasMoreTokens()) {
354 hash = hash ^ ((Integer.parseInt(stringTokenizer.nextToken(), base) * step) + step);
355 if (stopper > 0 && step == stopper) {
363 private static int calculateIpv4MatchHash(final Ipv4Match layer3Match) {
365 Ipv4Prefix ipv4Destination = layer3Match.getIpv4Destination();
366 if (null != ipv4Destination) {
367 hash += calculateIpv4PrefixHash(ipv4Destination);
370 Ipv4Prefix ipv4Source = layer3Match.getIpv4Source();
372 if (null != ipv4Source) {
373 hash += calculateIpv4PrefixHash(ipv4Source);
376 //TODO : add calculation of hashes for augmentations
380 private static int calculateArpMatchHash(final ArpMatch layer3Match) {
382 Integer arpOp = layer3Match.getArpOp();
384 hash += arpOp.intValue();
386 ArpSourceHardwareAddress arpSourceHardwareAddress = layer3Match.getArpSourceHardwareAddress();
387 if (null != arpSourceHardwareAddress) {
388 hash += calculateMacAddressHash(arpSourceHardwareAddress.getAddress());
389 hash += calculateMacAddressHash(arpSourceHardwareAddress.getMask());
392 Ipv4Prefix sourceTransportAddress = layer3Match.getArpSourceTransportAddress();
393 if (null != sourceTransportAddress) {
394 hash += calculateIpv4PrefixHash(sourceTransportAddress);
397 ArpTargetHardwareAddress arpTargetHardwareAddress = layer3Match.getArpTargetHardwareAddress();
398 if (null != arpTargetHardwareAddress) {
399 hash += calculateMacAddressHash(arpTargetHardwareAddress.getAddress());
400 hash += calculateMacAddressHash(arpTargetHardwareAddress.getMask());
403 Ipv4Prefix targetTransportAddress = layer3Match.getArpTargetTransportAddress();
404 if (null != targetTransportAddress) {
405 hash += calculateIpv4PrefixHash(targetTransportAddress);
411 public static int calculateIpv4PrefixHash(final Ipv4Prefix ipv4Prefix) {
413 StringTokenizer prefixAsArray = new StringTokenizer(ipv4Prefix.getValue(), "/");
414 if (prefixAsArray.countTokens() == 2) {
415 String address = prefixAsArray.nextToken();
416 Integer mask = Integer.parseInt(prefixAsArray.nextToken());
417 int numberOfAddressPartsToUse = (int) Math.ceil(mask.doubleValue() / 8);
418 hash += calculateIpAdressHash(address, numberOfAddressPartsToUse, BASE_10);
419 hash += mask.shortValue();
425 private static int calculateIpAdressHash(final String address, int numberOfParts, int base) {
426 StringTokenizer stringTokenizer = new StringTokenizer(address, ".");
427 int hash = parseTokens(stringTokenizer, numberOfParts, base);
431 private static int calculateIpMatchHash(final IpMatch ipMatch) {
433 Short ipEcn = ipMatch.getIpEcn();
435 hash += ipEcn.shortValue();
437 Short ipProtocol = ipMatch.getIpProtocol();
438 if (null != ipProtocol) {
442 Short ipDscp = ipMatch.getIpDscp().getValue();
443 if (null != ipDscp) {
447 IpVersion ipVersion = ipMatch.getIpProto();
448 if (null != ipVersion) {
449 hash += ipVersion.getIntValue();
454 private static int calculateNodeConnectorIdHash(final NodeConnectorId inPhyPort) {
456 hash += Integer.valueOf(inPhyPort.getValue());
460 private static int calculateIcmpV6MatchHash(final Icmpv6Match icmpv6Match) {
462 if (null != icmpv6Match.getIcmpv6Code()) {
463 hash += icmpv6Match.getIcmpv6Code();
465 if (null != icmpv6Match.getIcmpv6Type()) {
466 hash += icmpv6Match.getIcmpv6Type();
471 public static int calculateIcmpV4MatchHash(final Icmpv4Match icmpv4Match) {
473 if (null != icmpv4Match.getIcmpv4Code()) {
474 hash += icmpv4Match.getIcmpv4Code();
476 if (null != icmpv4Match.getIcmpv4Type()) {
477 hash += icmpv4Match.getIcmpv4Type();