Merge "Fixing + testing meter services"
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / util / HashUtil.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.impl.util;
10
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;
46
47 /**
48  * Created by Martin Bobak <mbobak@cisco.com> on 8.4.2015.
49  */
50 public final class HashUtil {
51
52     private static final int BASE_16 = 16;
53     private static final int BASE_10 = 10;
54
55     private HashUtil() {
56
57         throw new IllegalStateException("This class should not be instantiated.");
58     }
59
60     public static int calculateEthernetMatchHash(EthernetMatch ethernetMatch) {
61         int hash = 0;
62
63         EthernetType ethernetType = ethernetMatch.getEthernetType();
64         if (null != ethernetType) {
65             hash += ethernetType.getType().getValue();
66         }
67
68         EthernetDestination ethernetDestination = ethernetMatch.getEthernetDestination();
69         if (null != ethernetDestination) {
70             hash += calculateEthernetDestinationHash(ethernetDestination);
71         }
72
73         EthernetSource ethernetSource = ethernetMatch.getEthernetSource();
74         if (null != ethernetSource) {
75             hash += calculateEthenetSourceHash(ethernetSource);
76         }
77
78         return hash;
79     }
80
81     public static int calculateEthenetSourceHash(EthernetSource ethernetSource) {
82         int hash = calculateMacAddressHash(ethernetSource.getAddress());
83         hash += calculateMacAddressHash(ethernetSource.getMask());
84         return hash;
85     }
86
87     public static int calculateEthernetDestinationHash(EthernetDestination ethernetDestination) {
88         int hash = calculateMacAddressHash(ethernetDestination.getAddress());
89         hash += calculateMacAddressHash(ethernetDestination.getMask());
90         return hash;
91     }
92
93     public static int calculateMacAddressHash(MacAddress macAddress) {
94         int hash = 0;
95         if (null != macAddress) {
96             StringTokenizer stringTokenizer = new StringTokenizer(macAddress.getValue(), ":");
97             hash = parseTokens(stringTokenizer, BASE_16);
98         }
99         return hash;
100     }
101
102     public static int calculateMatchHash(final Match match) {
103         int hash = 0;
104         int subHash = 0;
105         int base = 0;
106         if (null != match) {
107             if (null != match.getEthernetMatch()) {
108                 hash = 1 << base;
109                 subHash += calculateEthernetMatchHash(match.getEthernetMatch());
110             }
111             base++;
112             if (null != match.getIcmpv4Match()) {
113                 hash = 1 << base;
114                 subHash += calculateIcmpV4MatchHash(match.getIcmpv4Match());
115             }
116             base++;
117             if (null != match.getIcmpv6Match()) {
118                 hash = 1 << base;
119                 subHash += calculateIcmpV6MatchHash(match.getIcmpv6Match());
120             }
121             base++;
122             if (null != match.getInPhyPort()) {
123                 hash = 1 << base;
124                 subHash += calculateNodeConnectorIdHash(match.getInPhyPort());
125             }
126             base++;
127             if (null != match.getInPort()) {
128                 hash = 1 << base;
129                 subHash += calculateNodeConnectorIdHash(match.getInPort());
130             }
131             base++;
132             if (null != match.getIpMatch()) {
133                 hash = 1 << base;
134                 subHash += calculateIpMatchHash(match.getIpMatch());
135             }
136             base++;
137             if (null != match.getLayer3Match()) {
138                 hash = 1 << base;
139                 subHash += calculateLayer3MatchHash(match.getLayer3Match());
140             }
141             base++;
142             if (null != match.getLayer4Match()) {
143                 hash = 1 << base;
144                 subHash += calculateLayer4MatchHash(match.getLayer4Match());
145             }
146             base++;
147             if (null != match.getIcmpv6Match()) {
148                 hash = 1 << base;
149                 subHash += calculateIcmpv6MatchHash(match.getIcmpv6Match());
150             }
151             base++;
152             if (null != match.getMetadata()) {
153                 hash = 1 << base;
154                 subHash += calculateMetadataHash(match.getMetadata());
155             }
156             base++;
157             if (null != match.getProtocolMatchFields()) {
158                 hash = 1 << base;
159                 subHash += calculateProtocolMatchFieldsHash(match.getProtocolMatchFields());
160             }
161             base++;
162             if (null != match.getTcpFlagMatch()) {
163                 hash = 1 << base;
164                 subHash += calculateTcpFlagMatch(match.getTcpFlagMatch());
165             }
166             base++;
167             if (null != match.getVlanMatch()) {
168                 hash = 1 << base;
169                 subHash += calculateVlanMatchHash(match.getVlanMatch());
170             }
171             base++;
172             if (null != match.getTunnel()) {
173                 hash = 1 << base;
174                 subHash += calculateTunnelHash(match.getTunnel());
175             }
176         }
177         return hash + subHash;
178     }
179
180     private static int calculateTunnelHash(final Tunnel tunnel) {
181         int hash = 0;
182         BigInteger tunnelId = tunnel.getTunnelId();
183         if (null != tunnelId) {
184             hash += tunnelId.intValue();
185         }
186
187         BigInteger tunnelMask = tunnel.getTunnelMask();
188         if (null != tunnelMask) {
189             hash += tunnelMask.intValue();
190         }
191         return hash;
192     }
193
194     private static int calculateVlanMatchHash(final VlanMatch vlanMatch) {
195         int hash = 0;
196
197         VlanId vlanId = vlanMatch.getVlanId();
198         if (null != vlanId) {
199             hash += vlanId.getVlanId().getValue().intValue();
200         }
201
202         VlanPcp vlanPcp = vlanMatch.getVlanPcp();
203         if (null != vlanPcp) {
204             hash += vlanPcp.getValue().shortValue();
205         }
206
207         return hash;
208     }
209
210     private static int calculateTcpFlagMatch(final TcpFlagMatch tcpFlagMatch) {
211         int hash = tcpFlagMatch.getTcpFlag().intValue();
212         return hash;
213     }
214
215     private static int calculateProtocolMatchFieldsHash(final ProtocolMatchFields protocolMatchFields) {
216         int hash = 0;
217         Short mplsBos = protocolMatchFields.getMplsBos();
218         if (null != mplsBos) {
219             hash += mplsBos.intValue();
220         }
221         Short mplsTc = protocolMatchFields.getMplsTc();
222         if (null != mplsTc) {
223             hash += mplsTc.intValue();
224         }
225         Pbb pbb = protocolMatchFields.getPbb();
226         if (null != pbb) {
227             if (null != pbb.getPbbIsid()) {
228                 hash += pbb.getPbbIsid().intValue();
229             }
230             if (null != pbb.getPbbMask()) {
231                 hash += pbb.getPbbMask().intValue();
232             }
233         }
234         Long mplsLabel = protocolMatchFields.getMplsLabel();
235         if (null != mplsLabel) {
236             hash += mplsLabel.intValue();
237         }
238         return hash;
239     }
240
241     private static int calculateMetadataHash(final Metadata metadata) {
242         int hash = metadata.getMetadata().intValue();
243         hash += metadata.getMetadataMask().intValue();
244         return hash;
245     }
246
247     private static int calculateIcmpv6MatchHash(final Icmpv6Match icmpv6Match) {
248         int hash = icmpv6Match.getIcmpv6Code().intValue();
249         hash += icmpv6Match.getIcmpv6Type().intValue();
250         return hash;
251     }
252
253     private static int calculateLayer4MatchHash(final Layer4Match layer4Match) {
254         int hash = 0;
255         if (layer4Match instanceof SctpMatch) {
256             hash += calculateSctpMatchHash((SctpMatch) layer4Match);
257         }
258
259         if (layer4Match instanceof TcpMatch) {
260             hash += calculateTcpMatchHash((TcpMatch) layer4Match);
261         }
262         if (layer4Match instanceof UdpMatch) {
263             hash += calculateUdpMatchHash((UdpMatch) layer4Match);
264         }
265         return hash;
266     }
267
268     private static int calculateUdpMatchHash(final UdpMatch layer4Match) {
269         int hash = 0;
270         return hash;
271     }
272
273     private static int calculateTcpMatchHash(final TcpMatch layer4Match) {
274         int hash = 0;
275         PortNumber sourcePort = layer4Match.getTcpSourcePort();
276         if (null != sourcePort) {
277             hash += sourcePort.getValue().intValue();
278         }
279
280         PortNumber destinationPort = layer4Match.getTcpDestinationPort();
281         if (null != destinationPort) {
282             hash += destinationPort.getValue().intValue();
283         }
284         return hash;
285     }
286
287     private static int calculateSctpMatchHash(final SctpMatch layer4Match) {
288         int hash = 0;
289
290         PortNumber portNumber = layer4Match.getSctpDestinationPort();
291         if (null != portNumber) {
292             hash += portNumber.getValue().intValue();
293         }
294
295         PortNumber sourcePort = layer4Match.getSctpSourcePort();
296         if (null != sourcePort) {
297             hash += sourcePort.getValue().intValue();
298         }
299         return hash;
300     }
301
302     private static int calculateLayer3MatchHash(final Layer3Match layer3Match) {
303         int hash = 0;
304         if (layer3Match instanceof ArpMatch) {
305             hash += calculateArpMatchHash((ArpMatch) layer3Match);
306         }
307         if (layer3Match instanceof Ipv4Match) {
308             hash += calculateIpv4MatchHash((Ipv4Match) layer3Match);
309         }
310         if (layer3Match instanceof Ipv6Match) {
311             hash += calculateIpv6MatchHash((Ipv6Match) layer3Match);
312
313         }
314         if (layer3Match instanceof TunnelIpv4Match) {
315             hash += calculateTunnelIpv4Hash((TunnelIpv4Match) layer3Match);
316         }
317         return hash;
318     }
319
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);
325         return hash;
326     }
327
328     private static int calculateIpv6MatchHash(final Ipv6Match layer3Match) {
329         int hash = 0;
330         Ipv6Prefix ipv6Destination = layer3Match.getIpv6Destination();
331         if (null != ipv6Destination) {
332             hash += calculateIpv6PrefixHash(ipv6Destination);
333         }
334         return hash;
335     }
336
337
338     public static int calculateIpv6PrefixHash(final Ipv6Prefix ipv6Prefix) {
339         StringTokenizer stringTokenizer = new StringTokenizer(ipv6Prefix.getValue(), ":");
340         int hash = parseTokens(stringTokenizer, BASE_16);
341         return hash;
342     }
343
344     private static int parseTokens(final StringTokenizer stringTokenizer, int base) {
345         return parseTokens(stringTokenizer, 0, base);
346     }
347
348     private static int parseTokens(final StringTokenizer stringTokenizer, int stopper, int base) {
349         int hash = 0;
350         if (stringTokenizer.countTokens() > 0) {
351             int step = 0;
352             while (stringTokenizer.hasMoreTokens()) {
353                 step++;
354                 hash = hash ^ ((Integer.parseInt(stringTokenizer.nextToken(), base) * step) + step);
355                 if (stopper > 0 && step == stopper) {
356                     break;
357                 }
358             }
359         }
360         return hash;
361     }
362
363     private static int calculateIpv4MatchHash(final Ipv4Match layer3Match) {
364         int hash = 0;
365         Ipv4Prefix ipv4Destination = layer3Match.getIpv4Destination();
366         if (null != ipv4Destination) {
367             hash += calculateIpv4PrefixHash(ipv4Destination);
368         }
369
370         Ipv4Prefix ipv4Source = layer3Match.getIpv4Source();
371
372         if (null != ipv4Source) {
373             hash += calculateIpv4PrefixHash(ipv4Source);
374         }
375
376         //TODO : add calculation of hashes for augmentations
377         return hash;
378     }
379
380     private static int calculateArpMatchHash(final ArpMatch layer3Match) {
381         int hash = 0;
382         Integer arpOp = layer3Match.getArpOp();
383         if (null != arpOp) {
384             hash += arpOp.intValue();
385         }
386         ArpSourceHardwareAddress arpSourceHardwareAddress = layer3Match.getArpSourceHardwareAddress();
387         if (null != arpSourceHardwareAddress) {
388             hash += calculateMacAddressHash(arpSourceHardwareAddress.getAddress());
389             hash += calculateMacAddressHash(arpSourceHardwareAddress.getMask());
390         }
391
392         Ipv4Prefix sourceTransportAddress = layer3Match.getArpSourceTransportAddress();
393         if (null != sourceTransportAddress) {
394             hash += calculateIpv4PrefixHash(sourceTransportAddress);
395         }
396
397         ArpTargetHardwareAddress arpTargetHardwareAddress = layer3Match.getArpTargetHardwareAddress();
398         if (null != arpTargetHardwareAddress) {
399             hash += calculateMacAddressHash(arpTargetHardwareAddress.getAddress());
400             hash += calculateMacAddressHash(arpTargetHardwareAddress.getMask());
401         }
402
403         Ipv4Prefix targetTransportAddress = layer3Match.getArpTargetTransportAddress();
404         if (null != targetTransportAddress) {
405             hash += calculateIpv4PrefixHash(targetTransportAddress);
406         }
407
408         return hash;
409     }
410
411     public static int calculateIpv4PrefixHash(final Ipv4Prefix ipv4Prefix) {
412         int hash = 0;
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();
420         }
421         return hash;
422     }
423
424
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);
428         return hash;
429     }
430
431     private static int calculateIpMatchHash(final IpMatch ipMatch) {
432         int hash = 0;
433         Short ipEcn = ipMatch.getIpEcn();
434         if (null != ipEcn) {
435             hash += ipEcn.shortValue();
436         }
437         Short ipProtocol = ipMatch.getIpProtocol();
438         if (null != ipProtocol) {
439             hash += ipProtocol;
440         }
441
442         Short ipDscp = ipMatch.getIpDscp().getValue();
443         if (null != ipDscp) {
444             hash += ipDscp;
445         }
446
447         IpVersion ipVersion = ipMatch.getIpProto();
448         if (null != ipVersion) {
449             hash += ipVersion.getIntValue();
450         }
451         return hash;
452     }
453
454     private static int calculateNodeConnectorIdHash(final NodeConnectorId inPhyPort) {
455         int hash = 0;
456         hash += Integer.valueOf(inPhyPort.getValue());
457         return hash;
458     }
459
460     private static int calculateIcmpV6MatchHash(final Icmpv6Match icmpv6Match) {
461         int hash = 0;
462         if (null != icmpv6Match.getIcmpv6Code()) {
463             hash += icmpv6Match.getIcmpv6Code();
464         }
465         if (null != icmpv6Match.getIcmpv6Type()) {
466             hash += icmpv6Match.getIcmpv6Type();
467         }
468         return hash;
469     }
470
471     public static int calculateIcmpV4MatchHash(final Icmpv4Match icmpv4Match) {
472         int hash = 0;
473         if (null != icmpv4Match.getIcmpv4Code()) {
474             hash += icmpv4Match.getIcmpv4Code();
475         }
476         if (null != icmpv4Match.getIcmpv4Type()) {
477             hash += icmpv4Match.getIcmpv4Type();
478         }
479         return hash;
480     }
481
482
483 }