Merge "BUG-5841: Enhances bulk-o-matic to stress test Data Store and Openflowplugin...
[openflowplugin.git] / applications / statistics-manager / src / main / java / org / opendaylight / openflowplugin / applications / statistics / manager / impl / helper / MatchComparatorHelper.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 package org.opendaylight.openflowplugin.applications.statistics.manager.impl.helper;
9
10 import java.math.BigInteger;
11 import java.net.Inet4Address;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.ArrayList;
15 import java.util.Arrays;
16
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddress;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddress;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
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.Layer3Match;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 import com.google.common.annotations.VisibleForTesting;
36 import com.google.common.net.InetAddresses;
37 import com.google.common.primitives.UnsignedBytes;
38
39 /**
40  * @author joe
41  * @author sai.marapareddy@gmail.com
42  *
43  */
44 public class MatchComparatorHelper {
45
46     private static final Logger LOG = LoggerFactory.getLogger(MatchComparatorHelper.class);
47     private static final int DEFAULT_SUBNET = 32;
48     private static final int IPV4_MASK_LENGTH = 32;
49     private static final int SHIFT_OCTET_1 = 24;
50     private static final int SHIFT_OCTET_2 = 16;
51     private static final int SHIFT_OCTET_3 = 8;
52     private static final int SHIFT_OCTET_4 = 0;
53     private static final int POSITION_OCTET_1 = 0;
54     private static final int POSITION_OCTET_2 = 1;
55     private static final int POSITION_OCTET_3 = 2;
56     private static final int POSITION_OCTET_4 = 3;
57     private static final String DEFAULT_ARBITRARY_BIT_MASK = "255.255.255.255";
58     private static final String PREFIX_SEPARATOR = "/";
59     private static final int IPV4_ADDRESS_LENGTH = 32;
60
61     /*
62      * Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in any case
63      * (upper or lower or mix). Ethernet Match which controller receives from switch is always an upper case string.
64      * Default EthernetMatch equals doesn't use equalsIgnoreCase() and hence it fails. E.g User provided mac address
65      * string in flow match is aa:bb:cc:dd:ee:ff and when controller fetch statistic data, openflow driver library
66      * returns AA:BB:CC:DD:EE:FF and default eqauls fails here.
67      */
68     @VisibleForTesting
69     static boolean ethernetMatchEquals(final EthernetMatch statsEthernetMatch, final EthernetMatch storedEthernetMatch) {
70         boolean verdict = true;
71         final Boolean checkNullValues = checkNullValues(statsEthernetMatch, storedEthernetMatch);
72         if (checkNullValues != null) {
73             verdict = checkNullValues;
74         } else {
75             verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetSource(),
76                     storedEthernetMatch.getEthernetSource());
77             if (verdict) {
78                 verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetDestination(),
79                         storedEthernetMatch.getEthernetDestination());
80             }
81             if (verdict) {
82                 if (statsEthernetMatch.getEthernetType() == null) {
83                     if (storedEthernetMatch.getEthernetType() != null) {
84                         verdict = false;
85                     }
86                 } else {
87                     verdict = statsEthernetMatch.getEthernetType().equals(storedEthernetMatch.getEthernetType());
88                 }
89             }
90         }
91         return verdict;
92     }
93
94     static boolean ethernetMatchFieldsEquals(final MacAddressFilter statsEthernetMatchFields,
95             final MacAddressFilter storedEthernetMatchFields) {
96         boolean verdict = true;
97         final Boolean checkNullValues = checkNullValues(statsEthernetMatchFields, storedEthernetMatchFields);
98         if (checkNullValues != null) {
99             verdict = checkNullValues;
100         } else {
101             verdict = macAddressEquals(statsEthernetMatchFields.getAddress(), storedEthernetMatchFields.getAddress());
102             if (verdict) {
103                 verdict = macAddressEquals(statsEthernetMatchFields.getMask(), storedEthernetMatchFields.getMask());
104             }
105         }
106         return verdict;
107     }
108
109     static boolean macAddressEquals(final MacAddress statsMacAddress, final MacAddress storedMacAddress) {
110         boolean verdict = true;
111         final Boolean checkNullValues = checkNullValues(statsMacAddress, storedMacAddress);
112         if (checkNullValues != null) {
113             verdict = checkNullValues;
114         } else {
115             verdict = statsMacAddress.getValue().equalsIgnoreCase(storedMacAddress.getValue());
116         }
117         return verdict;
118     }
119
120     @VisibleForTesting
121     static boolean layer3MatchEquals(final Layer3Match statsLayer3Match, final Layer3Match storedLayer3Match) {
122         boolean verdict = true;
123         if (statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4Match) {
124             final Ipv4Match statsIpv4Match = (Ipv4Match) statsLayer3Match;
125             final Ipv4Match storedIpv4Match = (Ipv4Match) storedLayer3Match;
126             verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(storedIpv4Match.getIpv4Destination(),
127                     statsIpv4Match.getIpv4Destination());
128             if (verdict) {
129                 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(statsIpv4Match.getIpv4Source(),
130                         storedIpv4Match.getIpv4Source());
131             }
132         } else if (statsLayer3Match instanceof Ipv6Match && storedLayer3Match instanceof Ipv6Match) {
133             final Ipv6Match statsIpv6Match = (Ipv6Match) statsLayer3Match;
134             final Ipv6Match storedIpv6Match = (Ipv6Match) storedLayer3Match;
135             verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(storedIpv6Match.getIpv6Destination(),
136                     statsIpv6Match.getIpv6Destination());
137             if (verdict) {
138                 verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(statsIpv6Match.getIpv6Source(),
139                         storedIpv6Match.getIpv6Source());
140             }
141         } else if (statsLayer3Match instanceof  Ipv4MatchArbitraryBitMask && storedLayer3Match instanceof Ipv4MatchArbitraryBitMask) {
142             // At this moment storedIpv4MatchArbitraryBitMask & statsIpv4MatchArbitraryBitMask will always have non null arbitrary masks.
143             // In case of no / null arbitrary mask, statsLayer3Match will be an instance of Ipv4Match.
144             // Eg:- stats -> 1.0.1.0/255.0.255.0  stored -> 1.1.1.0/255.0.255.0
145             final Ipv4MatchArbitraryBitMask statsIpv4MatchArbitraryBitMask= (Ipv4MatchArbitraryBitMask) statsLayer3Match;
146             final Ipv4MatchArbitraryBitMask storedIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) storedLayer3Match;
147             if ((storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null |
148                     storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null)) {
149                 if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
150                         String storedDstIpAddress = normalizeIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(),
151                                 storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
152                         String statsDstIpAddress = normalizeIpv4Address(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(),
153                                 statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
154                         if (MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue(),
155                                 statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue())) {
156                             verdict = MatchComparatorHelper.compareStringNullSafe(storedDstIpAddress,
157                                     statsDstIpAddress);
158                         } else {
159                             verdict = false;
160                             return verdict;
161                         }
162                 }
163                 if (storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
164                         String storedSrcIpAddress = normalizeIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask()
165                                 ,storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
166                         String statsSrcIpAddress = normalizeIpv4Address(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask()
167                                 ,statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
168                         if (MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue(),
169                                 statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue())) {
170                             verdict = MatchComparatorHelper.compareStringNullSafe(storedSrcIpAddress,
171                                     statsSrcIpAddress);
172                         } else {
173                             verdict = false;
174                         }
175                 }
176             } else {
177                 final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
178                 if (nullCheckOut != null) {
179                     verdict = nullCheckOut;
180                 } else {
181                     verdict = storedLayer3Match.equals(statsLayer3Match);
182                 }
183             }
184         } else if (statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4MatchArbitraryBitMask) {
185             // Here stored netmask is an instance of Ipv4MatchArbitraryBitMask, when it is pushed in to switch
186             // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes)
187             // Eg:- stats src/dest -> 1.1.1.0/24  stored src/dest -> 1.1.1.0/255.255.255.0
188             final Ipv4Match statsIpv4Match = (Ipv4Match) statsLayer3Match;
189             final Ipv4MatchArbitraryBitMask storedIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) storedLayer3Match;
190             if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) {
191                 Ipv4Prefix ipv4PrefixDestination;
192                 if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask() != null) {
193                     byte[] destByteMask = convertArbitraryMaskToByteArray(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask());
194                     ipv4PrefixDestination = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), destByteMask);
195                 } else {
196                     ipv4PrefixDestination = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask());
197                 }
198                 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixDestination, statsIpv4Match.getIpv4Destination());
199                 if (verdict == false) {
200                     return verdict;
201                 }
202             }
203             if (storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) {
204                 Ipv4Prefix ipv4PrefixSource;
205                 if (storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask() != null) {
206                     byte[] srcByteMask = convertArbitraryMaskToByteArray(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask());
207                     ipv4PrefixSource = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask(), srcByteMask);
208                 } else {
209                     ipv4PrefixSource = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask());
210                 }
211                 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, statsIpv4Match.getIpv4Source());
212             }
213         } else if (statsLayer3Match instanceof ArpMatch && storedLayer3Match instanceof ArpMatch) {
214             verdict = arpMatchEquals((ArpMatch)statsLayer3Match, (ArpMatch)storedLayer3Match);
215         } else {
216             final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
217             if (nullCheckOut != null) {
218                 verdict = nullCheckOut;
219             } else {
220                 verdict = storedLayer3Match.equals(statsLayer3Match);
221             }
222         }
223         return verdict;
224     }
225
226     static boolean arpMatchEquals(final ArpMatch statsArpMatch, final ArpMatch storedArpMatch) {
227
228         Integer statsOp = statsArpMatch.getArpOp();
229         Integer storedOp = storedArpMatch.getArpOp();
230
231         Boolean nullCheck = checkNullValues(statsOp, storedOp);
232         if (nullCheck != null) {
233             if (nullCheck == false) {
234                 return false;
235             }
236         } else if (!statsOp.equals(storedOp)) {
237             return false;
238         }
239
240         Ipv4Prefix statsIp = statsArpMatch.getArpSourceTransportAddress();
241         Ipv4Prefix storedIp = storedArpMatch.getArpSourceTransportAddress();
242         if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
243             return false;
244         }
245
246         statsIp = statsArpMatch.getArpTargetTransportAddress();
247         storedIp = storedArpMatch.getArpTargetTransportAddress();
248         if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
249             return false;
250         }
251
252         MacAddressFilter statsMac = statsArpMatch.getArpSourceHardwareAddress();
253         MacAddressFilter storedMac = storedArpMatch.getArpSourceHardwareAddress();
254         if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
255             return false;
256         }
257
258         statsMac = statsArpMatch.getArpTargetHardwareAddress();
259         storedMac = storedArpMatch.getArpTargetHardwareAddress();
260         if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
261             return false;
262         }
263
264         return true;
265     }
266
267
268     /**
269      * TODO: why don't we use the default Ipv4Prefix.equals()?
270      *
271      * @param statsIpAddress
272      * @param storedIpAddress
273      * @return true if IPv4prefixes equals
274      */
275     static boolean IpAddressEquals(final Ipv4Prefix statsIpAddress, final Ipv4Prefix storedIpAddress) {
276         final IntegerIpAddress statsIpAddressInt = MatchComparatorHelper.strIpToIntIp(statsIpAddress.getValue());
277         final IntegerIpAddress storedIpAddressInt = MatchComparatorHelper.strIpToIntIp(storedIpAddress.getValue());
278
279         if (ipAndMaskBasedMatch(statsIpAddressInt, storedIpAddressInt)) {
280             return true;
281         }
282         if (ipBasedMatch(statsIpAddressInt, storedIpAddressInt)) {
283             return true;
284         }
285         return false;
286     }
287
288     static boolean ipAndMaskBasedMatch(final IntegerIpAddress statsIpAddressInt,
289             final IntegerIpAddress storedIpAddressInt) {
290         return ((statsIpAddressInt.getIp() & statsIpAddressInt.getMask()) == (storedIpAddressInt.getIp() & storedIpAddressInt
291                 .getMask()));
292     }
293
294     static boolean ipBasedMatch(final IntegerIpAddress statsIpAddressInt, final IntegerIpAddress storedIpAddressInt) {
295         return (statsIpAddressInt.getIp() == storedIpAddressInt.getIp());
296     }
297
298
299     private static boolean IpAddressEquals(Ipv6Prefix statsIpv6, Ipv6Prefix storedIpv6) {
300         final String[] statsIpMask = statsIpv6.getValue().split("/");
301         final String[] storedIpMask = storedIpv6.getValue().split("/");
302         if (! (statsIpMask.length > 1 && storedIpMask.length > 1 &&  statsIpMask[1].equals(storedIpMask[1]))){
303             return false;
304         }
305         if (InetAddresses.forString(statsIpMask[0]).equals(InetAddresses.forString(storedIpMask[0]))){
306             return true;
307         }
308         return false;
309     }
310
311
312     static Boolean checkNullValues(final Object v1, final Object v2) {
313         Boolean verdict = null;
314         if (v1 == null && v2 != null) {
315             verdict = Boolean.FALSE;
316         } else if (v1 != null && v2 == null) {
317             verdict = Boolean.FALSE;
318         } else if (v1 == null && v2 == null) {
319             verdict = Boolean.TRUE;
320         }
321         return verdict;
322     }
323
324     static boolean compareIpv4PrefixNullSafe(final Ipv4Prefix statsIpv4, final Ipv4Prefix storedIpv4) {
325         boolean verdict = true;
326         final Boolean checkDestNullValuesOut = checkNullValues(storedIpv4, statsIpv4);
327         if (checkDestNullValuesOut != null) {
328             verdict = checkDestNullValuesOut;
329         } else if (!IpAddressEquals(statsIpv4, storedIpv4)) {
330             verdict = false;
331         }
332         return verdict;
333     }
334
335     static boolean compareStringNullSafe(final String stringA, final String stringB) {
336         boolean verdict = true;
337         final Boolean checkDestNullValuesOut = checkNullValues(stringA,stringB);
338         if (checkDestNullValuesOut != null) {
339             verdict = checkDestNullValuesOut;
340         } else if (!stringA.equals(stringB)) {
341             verdict = false;
342         }
343         return verdict;
344     }
345
346     private static boolean compareIpv6PrefixNullSafe(Ipv6Prefix statsIpv6, Ipv6Prefix storedIpv6) {
347         boolean verdict = true;
348         final Boolean checkDestNullValuesOut = checkNullValues(statsIpv6, storedIpv6);
349         if (checkDestNullValuesOut != null) {
350             verdict = checkDestNullValuesOut;
351         } else if (!IpAddressEquals(statsIpv6, storedIpv6)) {
352             verdict = false;
353         }
354         return verdict;
355     }
356
357     /**
358      * Method return integer version of ip address. Converted int will be mask if mask specified
359      */
360     static IntegerIpAddress strIpToIntIp(final String ipAddresss) {
361
362         final String[] parts = ipAddresss.split("/");
363         final String ip = parts[0];
364         int prefix;
365
366         if (parts.length < 2) {
367             prefix = DEFAULT_SUBNET;
368         } else {
369             prefix = Integer.parseInt(parts[1]);
370             if (prefix < 0 || prefix > IPV4_MASK_LENGTH) {
371                 final StringBuilder stringBuilder = new StringBuilder(
372                         "Valid values for mask are from range 0 - 32. Value ");
373                 stringBuilder.append(prefix);
374                 stringBuilder.append(" is invalid.");
375                 throw new IllegalStateException(stringBuilder.toString());
376             }
377         }
378
379         IntegerIpAddress integerIpAddress = null;
380
381         final Inet4Address addr = ((Inet4Address) InetAddresses.forString(ip));
382         final byte[] addrBytes = addr.getAddress();
383         // FIXME: what is meaning of anding with 0xFF? Probably could be removed.
384         final int ipInt = ((addrBytes[POSITION_OCTET_1] & 0xFF) << SHIFT_OCTET_1)
385                 | ((addrBytes[POSITION_OCTET_2] & 0xFF) << SHIFT_OCTET_2)
386                 | ((addrBytes[POSITION_OCTET_3] & 0xFF) << SHIFT_OCTET_3)
387                 | ((addrBytes[POSITION_OCTET_4] & 0xFF) << SHIFT_OCTET_4);
388
389         // FIXME: Is this valid?
390         final int mask = 0xffffffff << DEFAULT_SUBNET - prefix;
391
392         integerIpAddress = new IntegerIpAddress(ipInt, mask);
393
394         return integerIpAddress;
395     }
396
397     static boolean isArbitraryBitMask(byte[] byteMask) {
398         if (byteMask == null) {
399             return false;
400         } else {
401             ArrayList<Integer> integerMaskArrayList = new ArrayList<Integer>();
402             String maskInBits;
403             // converting byte array to bits
404             maskInBits = new BigInteger(1, byteMask).toString(2);
405             ArrayList<String> stringMaskArrayList = new ArrayList<String>(Arrays.asList(maskInBits.split("(?!^)")));
406             for(String string:stringMaskArrayList){
407                 integerMaskArrayList.add(Integer.parseInt(string));
408             }
409             return checkArbitraryBitMask(integerMaskArrayList);
410         }
411     }
412
413     static boolean checkArbitraryBitMask(ArrayList<Integer> arrayList) {
414         if (arrayList.size()>0 && arrayList.size()< IPV4_MASK_LENGTH ) {
415             // checks 0*1* case - Leading zeros in arrayList are truncated
416             return true;
417         } else {
418             //checks 1*0*1 case
419             for(int i=0; i<arrayList.size()-1;i++) {
420                 if(arrayList.get(i) ==0 && arrayList.get(i+1) == 1) {
421                     return true;
422                 }
423             }
424         }
425         return false;
426     }
427
428     static final byte[] convertArbitraryMaskToByteArray(DottedQuad mask) {
429         String maskValue;
430         if(mask.getValue() != null && mask != null){
431             maskValue  = mask.getValue();
432         } else maskValue = DEFAULT_ARBITRARY_BIT_MASK;
433         InetAddress maskInIpFormat = null;
434         try {
435             maskInIpFormat = InetAddress.getByName(maskValue);
436         } catch (UnknownHostException e) {
437             LOG.error("Failed to recognize the host while converting mask ", e);
438         }
439         byte[] bytes = maskInIpFormat.getAddress();
440         return bytes;
441     }
442
443
444     static String normalizeIpv4Address(Ipv4Address ipAddress, DottedQuad netMask) {
445         String actualIpAddress="";
446         String[] netMaskParts = netMask.getValue().split("\\.");
447         String[] ipAddressParts = ipAddress.getValue().split("\\.");
448
449         for (int i=0; i<ipAddressParts.length;i++) {
450             int integerFormatIpAddress=Integer.parseInt(ipAddressParts[i]);
451             int integerFormatNetMask=Integer.parseInt(netMaskParts[i]);
452             int ipAddressPart=(integerFormatIpAddress) & (integerFormatNetMask);
453             actualIpAddress += ipAddressPart;
454             if (i != ipAddressParts.length -1 ) {
455                 actualIpAddress = actualIpAddress+".";
456             }
457         }
458         return actualIpAddress;
459     }
460
461     static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final byte [] bytemask){
462         return createPrefix(ipv4Address, String.valueOf(countBits(bytemask)));
463     }
464
465     static int countBits(final byte[] mask) {
466         int netmask = 0;
467         for (byte b : mask) {
468             netmask += Integer.bitCount(UnsignedBytes.toInt(b));
469         }
470         return netmask;
471     }
472
473     static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address){
474         return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH);
475     }
476
477     static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final String mask){
478         /*
479          * Ipv4Address has already validated the address part of the prefix,
480          * It is mandated to comply to the same regexp as the address
481          * There is absolutely no point rerunning additional checks vs this
482          * Note - there is no canonical form check here!!!
483          */
484         if (null != mask && !mask.isEmpty()) {
485             return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + mask);
486         } else {
487             return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH);
488         }
489     }
490 }