2 * Copyright (c) 2015, 2017 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
8 package org.opendaylight.openflowplugin.impl.util;
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.net.InetAddresses;
12 import com.google.common.primitives.UnsignedBytes;
13 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
14 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
15 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchArbitraryBitMask;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 import java.math.BigInteger;
32 import java.net.Inet4Address;
33 import java.net.InetAddress;
34 import java.net.UnknownHostException;
35 import java.util.ArrayList;
36 import java.util.Arrays;
40 * @author sai.marapareddy@gmail.com
43 public class MatchComparatorHelper {
45 private static final Logger LOG = LoggerFactory.getLogger(MatchComparatorHelper.class);
46 private static final int DEFAULT_SUBNET = 32;
47 private static final int IPV4_MASK_LENGTH = 32;
48 private static final int SHIFT_OCTET_1 = 24;
49 private static final int SHIFT_OCTET_2 = 16;
50 private static final int SHIFT_OCTET_3 = 8;
51 private static final int SHIFT_OCTET_4 = 0;
52 private static final int POSITION_OCTET_1 = 0;
53 private static final int POSITION_OCTET_2 = 1;
54 private static final int POSITION_OCTET_3 = 2;
55 private static final int POSITION_OCTET_4 = 3;
56 private static final String DEFAULT_ARBITRARY_BIT_MASK = "255.255.255.255";
57 private static final String DEFAULT_IPV6_ARBITRARY_BIT_MASK = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff";
58 private static final String PREFIX_SEPARATOR = "/";
59 private static final int IPV4_ADDRESS_LENGTH = 32;
60 private static final int IPV6_ADDRESS_LENGTH = 128;
61 private static final int BYTE_SIZE = 8;
62 private static final String NO_ETH_MASK = "ff:ff:ff:ff:ff:ff";
65 * Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in any case
66 * (upper or lower or mix). Ethernet Match which controller receives from switch is always an upper case string.
67 * Default EthernetMatch equals doesn't use equalsIgnoreCase() and hence it fails. E.g User provided mac address
68 * string in flow match is aa:bb:cc:dd:ee:ff and when controller fetch statistic data, openflow driver library
69 * returns AA:BB:CC:DD:EE:FF and default eqauls fails here.
72 static boolean ethernetMatchEquals(final EthernetMatch statsEthernetMatch, final EthernetMatch storedEthernetMatch) {
73 boolean verdict = true;
74 final Boolean checkNullValues = checkNullValues(statsEthernetMatch, storedEthernetMatch);
75 if (checkNullValues != null) {
76 verdict = checkNullValues;
78 verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetSource(),
79 storedEthernetMatch.getEthernetSource());
81 verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetDestination(),
82 storedEthernetMatch.getEthernetDestination());
85 if (statsEthernetMatch.getEthernetType() == null) {
86 if (storedEthernetMatch.getEthernetType() != null) {
90 verdict = statsEthernetMatch.getEthernetType().equals(storedEthernetMatch.getEthernetType());
97 static boolean ethernetMatchFieldsEquals(final MacAddressFilter statsEthernetMatchFields,
98 final MacAddressFilter storedEthernetMatchFields) {
99 boolean verdict = true;
100 final Boolean checkNullValues = checkNullValues(statsEthernetMatchFields, storedEthernetMatchFields);
101 if (checkNullValues != null) {
102 verdict = checkNullValues;
104 verdict = macAddressEquals(statsEthernetMatchFields.getAddress(), storedEthernetMatchFields.getAddress());
106 verdict = macAddressMaskEquals(statsEthernetMatchFields.getMask(), storedEthernetMatchFields.getMask());
112 static boolean macAddressEquals(final MacAddress statsMacAddress, final MacAddress storedMacAddress) {
113 boolean verdict = true;
114 final Boolean checkNullValues = checkNullValues(statsMacAddress, storedMacAddress);
115 if (checkNullValues != null) {
116 verdict = checkNullValues;
118 verdict = statsMacAddress.getValue().equalsIgnoreCase(storedMacAddress.getValue());
123 static boolean macAddressMaskEquals(final MacAddress statsMacAddressMask, final MacAddress storedMacAddressMask) {
124 boolean verdict = true;
125 //User sent the mask with all bit set, which actually means no mask. Switch might just ignore it.
126 if(statsMacAddressMask == null && storedMacAddressMask != null &&
127 storedMacAddressMask.getValue().equalsIgnoreCase(NO_ETH_MASK)) {
130 final Boolean checkNullValues = checkNullValues(statsMacAddressMask, storedMacAddressMask);
131 if (checkNullValues != null) {
132 verdict = checkNullValues;
134 verdict = statsMacAddressMask.getValue().equalsIgnoreCase(storedMacAddressMask.getValue());
140 static boolean layer3MatchEquals(final Layer3Match statsLayer3Match, final Layer3Match storedLayer3Match) {
141 boolean verdict = true;
142 if (statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4Match) {
143 final Ipv4Match statsIpv4Match = (Ipv4Match) statsLayer3Match;
144 final Ipv4Match storedIpv4Match = (Ipv4Match) storedLayer3Match;
145 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(storedIpv4Match.getIpv4Destination(),
146 statsIpv4Match.getIpv4Destination());
148 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(statsIpv4Match.getIpv4Source(),
149 storedIpv4Match.getIpv4Source());
151 } else if (statsLayer3Match instanceof Ipv6Match && storedLayer3Match instanceof Ipv6Match) {
152 final Ipv6Match statsIpv6Match = (Ipv6Match) statsLayer3Match;
153 final Ipv6Match storedIpv6Match = (Ipv6Match) storedLayer3Match;
154 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(storedIpv6Match.getIpv6Destination(),
155 statsIpv6Match.getIpv6Destination());
157 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(statsIpv6Match.getIpv6Source(),
158 storedIpv6Match.getIpv6Source());
160 } else if (statsLayer3Match instanceof Ipv4MatchArbitraryBitMask && storedLayer3Match instanceof Ipv4MatchArbitraryBitMask) {
161 // At this moment storedIpv4MatchArbitraryBitMask & statsIpv4MatchArbitraryBitMask will always have non null arbitrary masks.
162 // In case of no / null arbitrary mask, statsLayer3Match will be an instance of Ipv4Match.
163 // Eg:- stats -> 1.0.1.0/255.0.255.0 stored -> 1.1.1.0/255.0.255.0
164 final Ipv4MatchArbitraryBitMask statsIpv4MatchArbitraryBitMask= (Ipv4MatchArbitraryBitMask) statsLayer3Match;
165 final Ipv4MatchArbitraryBitMask storedIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) storedLayer3Match;
166 if ((storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null |
167 storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null)) {
168 if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
169 String storedDstIpAddress = normalizeIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(),
170 storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
171 String statsDstIpAddress = normalizeIpv4Address(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(),
172 statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
173 if (MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue(),
174 statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue())) {
175 verdict = MatchComparatorHelper.compareStringNullSafe(storedDstIpAddress,
182 if (storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
183 String storedSrcIpAddress = normalizeIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask()
184 ,storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
185 String statsSrcIpAddress = normalizeIpv4Address(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask()
186 ,statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
187 if (MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue(),
188 statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue())) {
189 verdict = MatchComparatorHelper.compareStringNullSafe(storedSrcIpAddress,
196 final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
197 if (nullCheckOut != null) {
198 verdict = nullCheckOut;
200 verdict = storedLayer3Match.equals(statsLayer3Match);
203 } else if (statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4MatchArbitraryBitMask) {
204 // Here stored netmask is an instance of Ipv4MatchArbitraryBitMask, when it is pushed in to switch
205 // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes)
206 // Eg:- stats src/dest -> 1.1.1.0/24 stored src/dest -> 1.1.1.0/255.255.255.0
207 final Ipv4Match statsIpv4Match = (Ipv4Match) statsLayer3Match;
208 final Ipv4MatchArbitraryBitMask storedIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) storedLayer3Match;
209 if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
210 Ipv4Prefix ipv4PrefixDestination;
211 if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask() != null) {
212 byte[] destByteMask = convertArbitraryMaskToByteArray(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
213 ipv4PrefixDestination = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), destByteMask);
215 ipv4PrefixDestination = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask());
217 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixDestination, statsIpv4Match.getIpv4Destination());
218 if (verdict == false) {
222 if (storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
223 Ipv4Prefix ipv4PrefixSource;
224 if (storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask() != null) {
225 byte[] srcByteMask = convertArbitraryMaskToByteArray(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
226 ipv4PrefixSource = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask(), srcByteMask);
228 ipv4PrefixSource = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask());
230 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, statsIpv4Match.getIpv4Source());
232 } else if (statsLayer3Match instanceof Ipv4MatchArbitraryBitMask && storedLayer3Match instanceof Ipv4Match) {
233 // Here stored netmask is an instance of Ipv4MatchArbitraryBitMask, when it is pushed in to switch
234 // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes)
235 // Eg:- stats src/dest -> 1.1.1.0/24 stored src/dest -> 1.1.1.0/255.255.255.0
236 final Ipv4Match storedIpv4Match = (Ipv4Match) storedLayer3Match;
237 final Ipv4MatchArbitraryBitMask statsIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) statsLayer3Match;
238 if (statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
239 Ipv4Prefix ipv4PrefixDestination;
240 if (statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask() != null) {
241 byte[] destByteMask = convertArbitraryMaskToByteArray(statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
242 ipv4PrefixDestination = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), destByteMask);
244 ipv4PrefixDestination = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask());
246 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixDestination, storedIpv4Match.getIpv4Destination());
247 if (verdict == false) {
251 if (statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
252 Ipv4Prefix ipv4PrefixSource;
253 if (statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask() != null) {
254 byte[] srcByteMask = convertArbitraryMaskToByteArray(statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
255 ipv4PrefixSource = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask(), srcByteMask);
257 ipv4PrefixSource = createPrefix(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask());
259 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, storedIpv4Match.getIpv4Source());
261 } else if (statsLayer3Match instanceof Ipv6MatchArbitraryBitMask && storedLayer3Match instanceof Ipv6MatchArbitraryBitMask) {
262 // At this moment storedIpv6MatchArbitraryBitMask & statsIpv6MatchArbitraryBitMask will always have non null arbitrary masks.
263 // In case of no / null arbitrary mask, statsLayer3Match will be an instance of Ipv6Match.
264 // Eg:- stats src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:0000:FFFF:FFFF:FFF0
265 // stored src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:0000:FFFF:FFFF:FFF0
266 final Ipv6MatchArbitraryBitMask statsIpv6MatchArbitraryBitMask= (Ipv6MatchArbitraryBitMask) statsLayer3Match;
267 final Ipv6MatchArbitraryBitMask storedIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) storedLayer3Match;
268 if ((storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null |
269 storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null)) {
270 if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) {
271 String storedDstIpAddress = normalizeIpv6Address(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(),
272 storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
273 String statsDstIpAddress = normalizeIpv6Address(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(),
274 statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
275 String storedDstMask = extractIpv6CanonicalForm(storedIpv6MatchArbitraryBitMask.
276 getIpv6DestinationArbitraryBitmask().getValue()).getHostAddress();
277 String statsDstMask = extractIpv6CanonicalForm(statsIpv6MatchArbitraryBitMask.
278 getIpv6DestinationArbitraryBitmask().getValue()).getHostAddress();
279 if (MatchComparatorHelper.compareStringNullSafe(storedDstMask,statsDstMask)) {
280 verdict = MatchComparatorHelper.compareStringNullSafe(storedDstIpAddress,
287 if (storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) {
288 String storedSrcIpAddress = normalizeIpv6Address(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask()
289 ,storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
290 String statsSrcIpAddress = normalizeIpv6Address(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask()
291 ,statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
292 String storedSrcMask = extractIpv6CanonicalForm(storedIpv6MatchArbitraryBitMask.
293 getIpv6SourceArbitraryBitmask().getValue()).getHostAddress();
294 String statsSrcMask = extractIpv6CanonicalForm(statsIpv6MatchArbitraryBitMask.
295 getIpv6SourceArbitraryBitmask().getValue()).getHostAddress();
296 if (MatchComparatorHelper.compareStringNullSafe(storedSrcMask, statsSrcMask)) {
297 verdict = MatchComparatorHelper.compareStringNullSafe(storedSrcIpAddress,
304 final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
305 if (nullCheckOut != null) {
306 verdict = nullCheckOut;
308 verdict = storedLayer3Match.equals(statsLayer3Match);
311 } else if (statsLayer3Match instanceof Ipv6Match && storedLayer3Match instanceof Ipv6MatchArbitraryBitMask) {
312 // Here stored netmask is an instance of Ipv6MatchArbitraryBitMask, when it is pushed in to switch
313 // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes)
314 // Eg:- stats src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/124
315 // stored src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFF0
316 final Ipv6Match statsIpv6Match = (Ipv6Match) statsLayer3Match;
317 final Ipv6MatchArbitraryBitMask storedIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) storedLayer3Match;
318 if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) {
319 Ipv6Prefix ipv6PrefixDestination;
320 if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask() != null) {
321 byte[] destByteMask = convertIpv6ArbitraryMaskToByteArray(storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
322 ipv6PrefixDestination = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(), destByteMask);
324 ipv6PrefixDestination = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask());
326 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixDestination, statsIpv6Match.getIpv6Destination());
327 if (verdict == false) {
331 if (storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) {
332 Ipv6Prefix ipv6PrefixSource;
333 if (storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask() != null) {
334 byte[] srcByteMask = convertIpv6ArbitraryMaskToByteArray(storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
335 ipv6PrefixSource = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask(), srcByteMask);
337 ipv6PrefixSource = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask());
339 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixSource, statsIpv6Match.getIpv6Source());
341 } else if (statsLayer3Match instanceof Ipv6MatchArbitraryBitMask && storedLayer3Match instanceof Ipv6Match) {
342 // Here stored netmask is an instance of Ipv6MatchArbitraryBitMask, when it is pushed in to switch
343 // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes)
344 // Eg:- stats src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/124
345 // stored src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFF0
346 final Ipv6Match storedIpv6Match = (Ipv6Match) storedLayer3Match;
347 final Ipv6MatchArbitraryBitMask statsIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) statsLayer3Match;
348 if (statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) {
349 Ipv6Prefix ipv6PrefixDestination;
350 if (statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask() != null) {
351 byte[] destByteMask = convertIpv6ArbitraryMaskToByteArray(statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask());
352 ipv6PrefixDestination = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(), destByteMask);
354 ipv6PrefixDestination = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask());
356 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixDestination, storedIpv6Match.getIpv6Destination());
357 if (verdict == false) {
361 if (statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) {
362 Ipv6Prefix ipv6PrefixSource;
363 if (statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask() != null) {
364 byte[] srcByteMask = convertIpv6ArbitraryMaskToByteArray(statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask());
365 ipv6PrefixSource = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask(), srcByteMask);
367 ipv6PrefixSource = createPrefix(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask());
369 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixSource, storedIpv6Match.getIpv6Source());
371 } else if (statsLayer3Match instanceof ArpMatch && storedLayer3Match instanceof ArpMatch) {
372 verdict = arpMatchEquals((ArpMatch)statsLayer3Match, (ArpMatch)storedLayer3Match);
374 final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
375 if (nullCheckOut != null) {
376 verdict = nullCheckOut;
378 verdict = storedLayer3Match.equals(statsLayer3Match);
384 static boolean arpMatchEquals(final ArpMatch statsArpMatch, final ArpMatch storedArpMatch) {
386 Integer statsOp = statsArpMatch.getArpOp();
387 Integer storedOp = storedArpMatch.getArpOp();
389 Boolean nullCheck = checkNullValues(statsOp, storedOp);
390 if (nullCheck != null) {
391 if (nullCheck == false) {
394 } else if (!statsOp.equals(storedOp)) {
398 Ipv4Prefix statsIp = statsArpMatch.getArpSourceTransportAddress();
399 Ipv4Prefix storedIp = storedArpMatch.getArpSourceTransportAddress();
400 if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
404 statsIp = statsArpMatch.getArpTargetTransportAddress();
405 storedIp = storedArpMatch.getArpTargetTransportAddress();
406 if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
410 MacAddressFilter statsMac = statsArpMatch.getArpSourceHardwareAddress();
411 MacAddressFilter storedMac = storedArpMatch.getArpSourceHardwareAddress();
412 if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
416 statsMac = statsArpMatch.getArpTargetHardwareAddress();
417 storedMac = storedArpMatch.getArpTargetHardwareAddress();
418 if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
427 * TODO: why don't we use the default Ipv4Prefix.equals()?
429 * @param statsIpAddress
430 * @param storedIpAddress
431 * @return true if IPv4prefixes equals
433 static boolean IpAddressEquals(final Ipv4Prefix statsIpAddress, final Ipv4Prefix storedIpAddress) {
434 final IntegerIpAddress statsIpAddressInt = MatchComparatorHelper.strIpToIntIp(statsIpAddress.getValue());
435 final IntegerIpAddress storedIpAddressInt = MatchComparatorHelper.strIpToIntIp(storedIpAddress.getValue());
437 if (ipAndMaskBasedMatch(statsIpAddressInt, storedIpAddressInt)) {
440 if (ipBasedMatch(statsIpAddressInt, storedIpAddressInt)) {
446 static boolean ipAndMaskBasedMatch(final IntegerIpAddress statsIpAddressInt,
447 final IntegerIpAddress storedIpAddressInt) {
448 return ((statsIpAddressInt.getIp() & statsIpAddressInt.getMask()) == (storedIpAddressInt.getIp() & storedIpAddressInt
452 static boolean ipBasedMatch(final IntegerIpAddress statsIpAddressInt, final IntegerIpAddress storedIpAddressInt) {
453 return (statsIpAddressInt.getIp() == storedIpAddressInt.getIp());
457 private static boolean IpAddressEquals(Ipv6Prefix statsIpv6, Ipv6Prefix storedIpv6) {
458 final String[] statsIpMask = statsIpv6.getValue().split("/");
459 final String[] storedIpMask = storedIpv6.getValue().split("/");
460 if (! (statsIpMask.length > 1 && storedIpMask.length > 1 && statsIpMask[1].equals(storedIpMask[1]))){
464 final int prefix = Integer.parseInt(statsIpMask[1]);
465 final int byteIndex = prefix/BYTE_SIZE;
466 final int lastByteBits = BYTE_SIZE - (prefix % BYTE_SIZE);
467 final InetAddress statsIp = InetAddresses.forString(statsIpMask[0]);
468 final InetAddress storedIp = InetAddresses.forString(storedIpMask[0]);
469 byte[] statsIpArr = Arrays.copyOfRange(statsIp.getAddress(),0,byteIndex+1);
470 byte[] storedIpArr = Arrays.copyOfRange(storedIp.getAddress(),0,byteIndex+1);
471 statsIpArr[byteIndex] = (byte) (statsIpArr[byteIndex] & (0XFF << lastByteBits));
472 storedIpArr[byteIndex] = (byte) (storedIpArr[byteIndex] & (0XFF << lastByteBits));
473 if(Arrays.equals(statsIpArr,storedIpArr)) {
479 static Boolean checkNullValues(final Object v1, final Object v2) {
480 Boolean verdict = null;
481 if (v1 == null && v2 != null) {
482 verdict = Boolean.FALSE;
483 } else if (v1 != null && v2 == null) {
484 verdict = Boolean.FALSE;
485 } else if (v1 == null && v2 == null) {
486 verdict = Boolean.TRUE;
491 static boolean compareIpv4PrefixNullSafe(final Ipv4Prefix statsIpv4, final Ipv4Prefix storedIpv4) {
492 boolean verdict = true;
493 final Boolean checkDestNullValuesOut = checkNullValues(storedIpv4, statsIpv4);
494 if (checkDestNullValuesOut != null) {
495 verdict = checkDestNullValuesOut;
496 } else if (!IpAddressEquals(statsIpv4, storedIpv4)) {
502 static boolean compareStringNullSafe(final String stringA, final String stringB) {
503 boolean verdict = true;
504 final Boolean checkDestNullValuesOut = checkNullValues(stringA,stringB);
505 if (checkDestNullValuesOut != null) {
506 verdict = checkDestNullValuesOut;
507 } else if (!stringA.equals(stringB)) {
513 private static boolean compareIpv6PrefixNullSafe(Ipv6Prefix statsIpv6, Ipv6Prefix storedIpv6) {
514 boolean verdict = true;
515 final Boolean checkDestNullValuesOut = checkNullValues(statsIpv6, storedIpv6);
516 if (checkDestNullValuesOut != null) {
517 verdict = checkDestNullValuesOut;
518 } else if (!IpAddressEquals(statsIpv6, storedIpv6)) {
525 * Method return integer version of ip address. Converted int will be mask if mask specified
527 static IntegerIpAddress strIpToIntIp(final String ipAddresss) {
529 final String[] parts = ipAddresss.split("/");
530 final String ip = parts[0];
533 if (parts.length < 2) {
534 prefix = DEFAULT_SUBNET;
536 prefix = Integer.parseInt(parts[1]);
537 if (prefix < 0 || prefix > IPV4_MASK_LENGTH) {
538 final StringBuilder stringBuilder = new StringBuilder(
539 "Valid values for mask are from range 0 - 32. Value ");
540 stringBuilder.append(prefix);
541 stringBuilder.append(" is invalid.");
542 throw new IllegalStateException(stringBuilder.toString());
546 IntegerIpAddress integerIpAddress = null;
548 final Inet4Address addr = ((Inet4Address) InetAddresses.forString(ip));
549 final byte[] addrBytes = addr.getAddress();
550 // FIXME: what is meaning of anding with 0xFF? Probably could be removed.
551 final int ipInt = ((addrBytes[POSITION_OCTET_1] & 0xFF) << SHIFT_OCTET_1)
552 | ((addrBytes[POSITION_OCTET_2] & 0xFF) << SHIFT_OCTET_2)
553 | ((addrBytes[POSITION_OCTET_3] & 0xFF) << SHIFT_OCTET_3)
554 | ((addrBytes[POSITION_OCTET_4] & 0xFF) << SHIFT_OCTET_4);
556 // FIXME: Is this valid?
557 final int mask = 0xffffffff << DEFAULT_SUBNET - prefix;
559 integerIpAddress = new IntegerIpAddress(ipInt, mask);
561 return integerIpAddress;
564 static boolean isArbitraryBitMask(byte[] byteMask) {
565 if (byteMask == null) {
568 ArrayList<Integer> integerMaskArrayList = new ArrayList<Integer>();
570 // converting byte array to bits
571 maskInBits = new BigInteger(1, byteMask).toString(2);
572 ArrayList<String> stringMaskArrayList = new ArrayList<String>(Arrays.asList(maskInBits.split("(?!^)")));
573 for(String string:stringMaskArrayList){
574 integerMaskArrayList.add(Integer.parseInt(string));
576 return checkArbitraryBitMask(integerMaskArrayList);
580 static boolean checkArbitraryBitMask(ArrayList<Integer> arrayList) {
581 if (arrayList.size()>0 && arrayList.size()< IPV4_MASK_LENGTH ) {
582 // checks 0*1* case - Leading zeros in arrayList are truncated
586 for(int i=0; i<arrayList.size()-1;i++) {
587 if(arrayList.get(i) ==0 && arrayList.get(i+1) == 1) {
595 static final byte[] convertArbitraryMaskToByteArray(DottedQuad mask) {
597 if (mask.getValue() != null) {
598 maskValue = mask.getValue();
600 maskValue = DEFAULT_ARBITRARY_BIT_MASK;
602 InetAddress maskInIpFormat = null;
604 maskInIpFormat = InetAddress.getByName(maskValue);
605 } catch (UnknownHostException e) {
606 LOG.error("Failed to recognize the host while converting mask ", e);
608 byte[] bytes = maskInIpFormat.getAddress();
612 private static final byte[] convertIpv6ArbitraryMaskToByteArray ( final Ipv6ArbitraryMask mask) {
614 if (mask.getValue() != null) {
615 maskValue = mask.getValue();
617 maskValue = DEFAULT_IPV6_ARBITRARY_BIT_MASK;
619 InetAddress maskInIpv6Format = null;
621 maskInIpv6Format = InetAddress.getByName(maskValue);
622 } catch (UnknownHostException e) {
623 LOG.error("Failed to convert string mask value to ipv6 format ", e);
625 return maskInIpv6Format.getAddress();
628 static String normalizeIpv4Address(Ipv4Address ipAddress, DottedQuad netMask) {
629 String actualIpAddress="";
630 String[] netMaskParts = netMask.getValue().split("\\.");
631 String[] ipAddressParts = ipAddress.getValue().split("\\.");
633 for (int i=0; i<ipAddressParts.length;i++) {
634 int integerFormatIpAddress=Integer.parseInt(ipAddressParts[i]);
635 int integerFormatNetMask=Integer.parseInt(netMaskParts[i]);
636 int ipAddressPart=(integerFormatIpAddress) & (integerFormatNetMask);
637 actualIpAddress += ipAddressPart;
638 if (i != ipAddressParts.length -1 ) {
639 actualIpAddress = actualIpAddress+".";
642 return actualIpAddress;
645 private static String normalizeIpv6Address(final Ipv6Address ipAddress, final Ipv6ArbitraryMask netMask) {
646 byte[] ipAddressParts = convertIpv6ToBytes(ipAddress.getValue());
647 byte[] netMaskParts = convertIpv6ToBytes(netMask.getValue());
648 byte[] actualIpv6Bytes = new byte[16];
650 for (int i=0; i<ipAddressParts.length;i++) {
651 byte ipAddressPart= (byte) (ipAddressParts[i] & netMaskParts[i]);
652 actualIpv6Bytes[i] = ipAddressPart;
654 InetAddress ipv6Address = null;
656 ipv6Address = InetAddress.getByAddress(actualIpv6Bytes);
657 } catch (UnknownHostException e) {
658 LOG.error("Failed to recognize the host while normalizing IPv6 address from bytes ", e);
660 return ipv6Address.getHostAddress();
663 private static byte[] convertIpv6ToBytes(final String ipv6Address) {
664 return extractIpv6CanonicalForm(ipv6Address).getAddress();
667 private static InetAddress extractIpv6CanonicalForm(final String ipv6Address) {
668 InetAddress address = null;
670 address = InetAddress.getByName(ipv6Address);
671 } catch (UnknownHostException e) {
672 LOG.error("Failed to recognize the host while converting IPv6 to bytes ", e);
677 static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final byte [] bytemask){
678 return createPrefix(ipv4Address, String.valueOf(countBits(bytemask)));
681 private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final byte [] bytemask) {
682 return createPrefix(ipv6Address, String.valueOf(countBits(bytemask)));
685 private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final String mask) {
686 if (mask != null && !mask.isEmpty()) {
687 return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + mask);
689 return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + IPV6_ADDRESS_LENGTH);
693 private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address) {
694 return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + IPV6_ADDRESS_LENGTH);
697 static int countBits(final byte[] mask) {
699 for (byte b : mask) {
700 netmask += Integer.bitCount(UnsignedBytes.toInt(b));
705 static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address){
706 return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH);
709 static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final String mask){
711 * Ipv4Address has already validated the address part of the prefix,
712 * It is mandated to comply to the same regexp as the address
713 * There is absolutely no point rerunning additional checks vs this
714 * Note - there is no canonical form check here!!!
716 if (null != mask && !mask.isEmpty()) {
717 return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + mask);
719 return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH);